pdf_ravager 0.1.0 → 0.2.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.
Files changed (39) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.rspec +3 -0
  4. data/CHANGELOG.md +8 -0
  5. data/Gemfile +2 -4
  6. data/README.md +14 -10
  7. data/Rakefile +2 -2
  8. data/lib/pdf_ravager/field_types/acro_form.rb +0 -8
  9. data/lib/pdf_ravager/kernel.rb +1 -0
  10. data/lib/pdf_ravager/ravager.rb +25 -54
  11. data/lib/pdf_ravager/strategies/acro_form.rb +25 -0
  12. data/lib/pdf_ravager/strategies/smart.rb +22 -0
  13. data/lib/pdf_ravager/strategies/xfa.rb +67 -0
  14. data/lib/pdf_ravager/template.rb +14 -4
  15. data/lib/pdf_ravager/version.rb +1 -1
  16. data/pdf_ravager.gemspec +2 -3
  17. data/spec/integration/checkbox_field/checked.png +0 -0
  18. data/spec/integration/checkbox_field/pdf +0 -0
  19. data/spec/integration/checkbox_field/spec.rb +31 -0
  20. data/spec/integration/checkbox_field/unchecked.png +0 -0
  21. data/spec/integration/checkbox_group/bar.png +0 -0
  22. data/spec/integration/checkbox_group/foo.png +0 -0
  23. data/spec/integration/checkbox_group/pdf +0 -0
  24. data/spec/integration/checkbox_group/spec.rb +49 -0
  25. data/spec/integration/checkbox_group/unchecked.png +0 -0
  26. data/spec/integration/integration_helper.rb +14 -3
  27. data/spec/integration/multiline_text_field/spec.rb +10 -11
  28. data/spec/integration/radio_field/empty.png +0 -0
  29. data/spec/integration/radio_field/no.png +0 -0
  30. data/spec/integration/radio_field/pdf +0 -0
  31. data/spec/integration/radio_field/spec.rb +45 -0
  32. data/spec/integration/radio_field/yes.png +0 -0
  33. data/spec/integration/text_field/spec.rb +11 -12
  34. data/spec/spec_helper.rb +4 -1
  35. data/spec/unit/fields/checkbox_spec.rb +25 -16
  36. data/spec/unit/kernel_spec.rb +14 -8
  37. data/spec/unit/template_spec.rb +91 -41
  38. data/spec/unit/unit_helper.rb +1 -1
  39. metadata +58 -63
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 78b00f06cc54b5f044001f621fc30d284a02410e
4
+ data.tar.gz: b9fac87df32a1e3033d2e73f622b0665e761b3da
5
+ SHA512:
6
+ metadata.gz: 8dc1d7f6bca130cb731862d507463df813775abc7cbff40a7f5313fe28e92b5e327677cc2103718621bbc0ae12687d88e692146428b93863e7bd5cec81ec1043
7
+ data.tar.gz: cba64b43ca4100a42d7b10e77daa5112fcac7ec4df066e2b2cdfe57c42dc1dc349c62c14a1e382d7315039763f29d8d69a2bad39a3618bbafb919604e3ff595c
data/.gitignore CHANGED
@@ -2,3 +2,4 @@ Gemfile.lock
2
2
  pkg/
3
3
  *.gem
4
4
  .bundle
5
+ coverage/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --tty
2
+ --color
3
+ --profile
data/CHANGELOG.md ADDED
@@ -0,0 +1,8 @@
1
+ ## 0.2.0
2
+
3
+ Features:
4
+
5
+ - Deprecate global `pdf` convenience method
6
+ - Deprecate name option to `PDFRavager::Template.new`
7
+ - Move PDF population methods into strategies
8
+ - Speed up PDF population by default (i.e. :smart strategy) by avoiding XFA
data/Gemfile CHANGED
@@ -5,9 +5,7 @@ gemspec
5
5
  platforms :jruby do
6
6
  # Necessary for `rake release` on JRuby
7
7
  gem "jruby-openssl", "~> 0.7.7"
8
+ gem 'bouncy-castle-java'
8
9
  end
9
10
 
10
- group :test do
11
- # Formats and colorizes test output
12
- gem "turn", "~> 0.9.6", :require => false
13
- end
11
+ gem "simplecov", "~> 0.8", :require => false
data/README.md CHANGED
@@ -1,21 +1,21 @@
1
1
  # PDF Ravager [![Build Status](https://secure.travis-ci.org/abevoelker/pdf_ravager.png)](http://travis-ci.org/abevoelker/pdf_ravager)
2
2
 
3
- Provides a simple DSL for easily filling out AcroForms PDF or XFA documents.
3
+ JRuby-only DSL for filling out AcroForms PDF or XFA documents.
4
4
 
5
5
  ## Description
6
6
 
7
7
  This library uses a combination of a simple DSL and a minimal façade over the
8
- last free version of the iText library to aid in filling out AcroForms PDF or
9
- XFA documents.
8
+ last free version of the Java iText library to aid in filling out AcroForms PDF
9
+ or XFA documents.
10
10
 
11
11
  ## Synopsis
12
12
 
13
13
  ```ruby
14
- require 'pdf_ravager/kernel'
14
+ require 'pdf_ravager'
15
15
 
16
- data = {name: 'Bob', gender: 'm', relation: 'Uncle' }
16
+ data = { name: 'Bob', gender: 'm', relation: 'Uncle' }
17
17
 
18
- template = pdf do |p|
18
+ template = PDFRavager::Template.new do |p|
19
19
  p.text 'name', data[:name]
20
20
  p.rich_text 'name_stylized', "<b>#{data[:name]}</b>"
21
21
  p.radio_group 'sex' do |rg|
@@ -40,20 +40,24 @@ template.ravage '/tmp/info.pdf', out_file: '/tmp/info_filled.pdf'
40
40
  template.ravage '/tmp/info.pdf', out_file: '/tmp/info_filled.pdf', read_only: true
41
41
  ```
42
42
 
43
- If you don't want the global `pdf` method, the default `require 'pdf_ravager'`
44
- actually doesn't add it. You just need to be more wordy in this case:
43
+ Although not recommended due to the pollution of the global namespace, in the
44
+ interest of brevity you can introduce a shorthand `pdf` method that is
45
+ equivalent to `PDFRavager::Template.new` by requiring `pdf_ravager/kernel`
46
+ instead of `pdf_ravager`:
45
47
 
46
48
  ```ruby
47
- require 'pdf_ravager'
49
+ require 'pdf_ravager/kernel'
48
50
 
49
51
  data = {name: 'Bob', gender: 'm', relation: 'Uncle' }
50
52
 
51
- template = PDFRavager::Template.new do |p|
53
+ template = pdf do |p|
52
54
  p.text 'name', data[:name]
53
55
  # ...
54
56
  end
55
57
  ```
56
58
 
59
+ Note: `pdf` has been deprecated and will be removed in a future release.
60
+
57
61
  ## Usage
58
62
 
59
63
  ### Field Names
data/Rakefile CHANGED
@@ -5,13 +5,13 @@ require 'bundler'
5
5
 
6
6
  Rake::TestTask.new('spec:unit') do |t|
7
7
  t.libs << ["lib", "spec"]
8
- t.pattern = "spec/**/*_spec.rb"
8
+ t.pattern = "spec/unit/**/*_spec.rb"
9
9
  end
10
10
 
11
11
  if RUBY_PLATFORM =~ /java/
12
12
  # Integration tests can only run on JRuby
13
13
  RSpec::Core::RakeTask.new('spec:integration') do |spec|
14
- spec.pattern = "spec/**/*spec.rb"
14
+ spec.pattern = "spec/integration/**/*spec.rb"
15
15
  spec.rspec_opts = ['--backtrace']
16
16
  end
17
17
 
@@ -23,14 +23,6 @@ module PDFRavager
23
23
  @value.to_s
24
24
  end
25
25
 
26
- def set_acro_form_value(acro_fields)
27
- begin
28
- acro_fields.setField(SOM.short_name(acro_form_name), acro_form_value)
29
- rescue java.lang.NullPointerException
30
- false
31
- end
32
- end
33
-
34
26
  end
35
27
  end
36
28
  end
@@ -2,6 +2,7 @@ require 'pdf_ravager/template'
2
2
 
3
3
  module Kernel
4
4
  def pdf(*args, &blk)
5
+ warn "[DEPRECATION] Please use `PDFRavager::Template.new` instead of `pdf`"
5
6
  PDFRavager::Template.new(*args, &blk)
6
7
  end
7
8
  end
@@ -1,3 +1,7 @@
1
+ require 'pdf_ravager/strategies/xfa'
2
+ require 'pdf_ravager/strategies/acro_form'
3
+ require 'pdf_ravager/strategies/smart'
4
+
1
5
  unless RUBY_PLATFORM =~ /java/
2
6
  raise "You can only ravage PDFs using JRuby, not #{RUBY_PLATFORM}!"
3
7
  end
@@ -8,71 +12,38 @@ require File.dirname(__FILE__) + '/../../vendor/iText-4.2.0'
8
12
 
9
13
  module PDFRavager
10
14
  class Ravager
11
- private_class_method :new
15
+ def self.ravage(*args, &blk)
16
+ warn "[DEPRECATION] Please use PDFRavager::Ravager's instance " +
17
+ "methods instead of the `::ravage` method"
18
+ new(*args, &blk).ravage
19
+ end
12
20
 
13
- def self.ravage(template, opts={})
21
+ def initialize(template, opts={})
22
+ @opts = opts
14
23
  opts = {:in_file => opts} if opts.is_a? String
15
- out = if opts[:out_file]
24
+ @out = if opts[:out_file]
16
25
  java.io.FileOutputStream.new(opts[:out_file])
17
26
  else
18
27
  java.io.ByteArrayOutputStream.new
19
28
  end
20
- ravager = new(template, opts.merge({:out => out}))
21
- ravager.send(:set_field_values)
22
- ravager.send(:set_read_only) if opts[:read_only]
23
- ravager.send(:destroy)
24
- out
25
- end
26
-
27
- private
28
-
29
- # instantiation is private because there is a lot of state mutation
30
- # and some invariants that need to be cleaned up. therefore, Ravager's
31
- # lifecycle is managed by the public class method `ravage`.
32
- def initialize(template, opts={})
33
- @template, @opts = template, opts
34
- @reader = com.lowagie.text.pdf.PdfReader.new(opts[:in_file])
35
- @stamper = com.lowagie.text.pdf.PdfStamper.new(@reader, opts[:out])
36
- @afields = @stamper.getAcroFields
37
- @xfa = @afields.getXfa
38
- @som = @xfa.getDatasetsSom
39
- @som_template = @xfa.getTemplateSom
40
- @type = @xfa.isXfaPresent ? :xfa : :acro_forms
41
- if @type == :xfa
42
- @xfa_type = @afields.getFields.empty? ? :dynamic : :static
43
- end
44
- end
45
-
46
- def destroy
47
- @stamper.close
48
- end
49
-
50
- def set_field_values
51
- case @type
29
+ @template = template
30
+ reader = com.lowagie.text.pdf.PdfReader.new(opts[:in_file])
31
+ @stamper = com.lowagie.text.pdf.PdfStamper.new(reader, @out)
32
+ @strategy = case template.strategy
52
33
  when :acro_forms
53
- @template.fields.each{|f| f.set_acro_form_value(@afields) }
34
+ Strategies::AcroForm.new(@stamper)
54
35
  when :xfa
55
- @template.fields.each do |f|
56
- f.set_acro_form_value(@afields) if f.respond_to? :set_acro_form_value
57
- f.set_xfa_value(@xfa) if f.respond_to? :set_xfa_value
58
- end
36
+ Strategies::XFA.new(@stamper)
37
+ when :smart
38
+ Strategies::Smart.new(@stamper)
59
39
  end
60
40
  end
61
41
 
62
- def set_read_only
63
- case @type
64
- when :acro_forms
65
- @stamper.setFormFlattening(true)
66
- when :xfa
67
- doc = Nokogiri::XML(Nokogiri::XML::Document.wrap(@xfa.getDomDocument).to_xml)
68
- doc.xpath("//*[local-name()='field']").each do |node|
69
- node["access"] = "readOnly"
70
- end
71
- @xfa.setDomDocument(doc.to_java)
72
- @xfa.setChanged(true)
73
- end
42
+ def ravage
43
+ @strategy.set_field_values(@template)
44
+ @strategy.set_read_only if @opts[:read_only]
45
+ @stamper.close
46
+ @out
74
47
  end
75
-
76
48
  end
77
-
78
49
  end
@@ -0,0 +1,25 @@
1
+ module PDFRavager
2
+ module Strategies
3
+ class AcroForm
4
+ def initialize(stamper)
5
+ @stamper = stamper
6
+ @afields = stamper.getAcroFields
7
+ end
8
+
9
+ def set_field_values(template)
10
+ template.fields.select{|f| f.respond_to?(:acro_form_value)}.select do |f|
11
+ begin
12
+ @afields.setField(FieldTypes::AcroForm::SOM.short_name(f.acro_form_name), f.acro_form_value)
13
+ rescue java.lang.NullPointerException
14
+ false
15
+ end
16
+ end
17
+ end
18
+
19
+ def set_read_only
20
+ @stamper.setFormFlattening(true)
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module PDFRavager
2
+ module Strategies
3
+ class Smart
4
+ def initialize(stamper)
5
+ @acro_form = Strategies::AcroForm.new(stamper)
6
+ @xfa = Strategies::XFA.new(stamper)
7
+ end
8
+
9
+ def set_field_values(template)
10
+ parsed_fields = @acro_form.set_field_values(template)
11
+ unparsed_fields = template.fields - parsed_fields
12
+ if unparsed_fields.any?
13
+ @xfa.set_field_values(Template.new{|t| t.fields = unparsed_fields })
14
+ end
15
+ end
16
+
17
+ def set_read_only
18
+ [@acro_form, @xfa].each(&:set_read_only)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,67 @@
1
+ module PDFRavager
2
+ module Strategies
3
+ class XFA
4
+ def initialize(stamper)
5
+ @xfa = stamper.getAcroFields.getXfa
6
+ end
7
+
8
+ def set_field_values(template)
9
+ # the double-load is to work around a Nokogiri bug I found:
10
+ # https://github.com/sparklemotion/nokogiri/issues/781
11
+ doc = Nokogiri::XML(Nokogiri::XML::Document.wrap(@xfa.getDomDocument).to_xml)
12
+ template.fields.select{|f| f.respond_to?(:set_xfa_value)}.each do |f|
13
+ # first, assume the user-provided field name is an xpath and use it directly:
14
+ strict_match =
15
+ begin
16
+ doc.xpath(f.xfa_name)
17
+ rescue Nokogiri::XML::XPath::SyntaxError
18
+ []
19
+ end
20
+ # otherwise, we'll loosely match the field name anywhere in the document:
21
+ loose_match = doc.xpath("//*[local-name()='field'][@name='#{f.xfa_name}']")
22
+ matched_nodes = strict_match.any? ? strict_match : loose_match
23
+ matched_nodes.each do |node|
24
+ value_node = node.at_xpath("*[local-name()='value']")
25
+ if value_node
26
+ text_node = value_node.at_xpath("*[local-name()='#{f.xfa_node_type}']")
27
+ if text_node
28
+ # Complete node structure already exists - just set the value
29
+ text_node.content = f.xfa_value
30
+ else
31
+ # <value> node exists, but without child <text> node
32
+ Nokogiri::XML::Builder.with(value_node) do |xml|
33
+ xml.text_ {
34
+ xml.send("#{f.xfa_node_type}_", f.xfa_value)
35
+ }
36
+ end
37
+ end
38
+ else
39
+ # No <value> node exists - create whole structure
40
+ Nokogiri::XML::Builder.with(node) do |xml|
41
+ xml.value_ {
42
+ xml.send("#{f.xfa_node_type}_") {
43
+ xml.text f.xfa_value
44
+ }
45
+ }
46
+ end
47
+ end
48
+ end
49
+ end
50
+ @xfa.tap do |x|
51
+ x.setDomDocument(doc.to_java)
52
+ x.setChanged(true)
53
+ end
54
+ end
55
+
56
+ def set_read_only
57
+ doc = Nokogiri::XML(Nokogiri::XML::Document.wrap(@xfa.getDomDocument).to_xml)
58
+ doc.xpath("//*[local-name()='field']").each do |node|
59
+ node["access"] = "readOnly"
60
+ end
61
+ @xfa.setDomDocument(doc.to_java)
62
+ @xfa.setChanged(true)
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -8,10 +8,20 @@ require 'pdf_ravager/ravager' if RUBY_PLATFORM =~ /java/
8
8
 
9
9
  module PDFRavager
10
10
  class Template
11
- attr_reader :name, :fields
11
+ attr_reader :name, :strategy
12
+ attr_accessor :fields
12
13
 
13
- def initialize(name=nil)
14
- @name, @fields = name, []
14
+ def initialize(opts={})
15
+ opts = {:name => opts} if opts.respond_to?(:to_sym)
16
+ unless opts[:name].nil?
17
+ warn "[DEPRECATION] Passing a name to `PDFRavager::Template.new` " +
18
+ "is deprecated and will be removed in 1.0.0"
19
+ end
20
+ @name, @strategy = opts[:name], (opts[:strategy] || :smart)
21
+ unless [:smart, :acro_forms, :xfa].include?(@strategy)
22
+ raise "Bad strategy '#{@strategy}'"
23
+ end
24
+ @fields = []
15
25
  yield self if block_given?
16
26
  end
17
27
 
@@ -45,7 +55,7 @@ module PDFRavager
45
55
 
46
56
  if RUBY_PLATFORM =~ /java/
47
57
  def ravage(file, opts={})
48
- PDFRavager::Ravager.ravage(self, opts.merge({:in_file => file}))
58
+ PDFRavager::Ravager.new(self, opts.merge({:in_file => file})).ravage
49
59
  end
50
60
  else
51
61
  def ravage(file, opts={})
@@ -1,3 +1,3 @@
1
1
  module PDFRavager
2
- VERSION = "0.1.0"
2
+ VERSION = '0.2.0'
3
3
  end
data/pdf_ravager.gemspec CHANGED
@@ -7,13 +7,12 @@ Gem::Specification.new do |s|
7
7
  s.authors = ['Abe Voelker']
8
8
  s.email = 'abe@abevoelker.com'
9
9
  s.homepage = 'https://github.com/abevoelker/pdf_ravager'
10
- s.summary = %q{DSL to aid filling out AcroForms PDF and XFA documents}
11
- s.description = %q{DSL to aid filling out AcroForms PDF and XFA documents}
10
+ s.summary = %q{JRuby-only DSL for filling out AcroForms PDF and XFA documents}
11
+ s.description = %q{JRuby-only DSL for filling out AcroForms PDF and XFA documents}
12
12
  s.license = 'MIT'
13
13
 
14
14
  s.add_dependency "nokogiri"
15
15
  s.add_development_dependency "bundler", "~> 1.0"
16
- s.add_development_dependency "minitest", "~> 4.1"
17
16
  s.add_development_dependency "rspec", "~> 2.11"
18
17
  s.add_development_dependency "rake", "~> 0.9"
19
18
  s.add_development_dependency "chunky_png", "~> 1.2"
Binary file
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
+
3
+ describe 'a PDF with a checkbox field' do
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'unchecked' do
7
+ let(:template) {
8
+ PDFRavager::Template.new
9
+ }
10
+ let(:expected) { File.join(File.dirname(__FILE__), "unchecked.png") }
11
+
12
+ it 'matches unchecked.png when rendered' do
13
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
14
+ expect(pix_diff).to eq(0)
15
+ end
16
+ end
17
+
18
+ context 'checked' do
19
+ let(:template) {
20
+ PDFRavager::Template.new do |t|
21
+ t.check 'CheckBox1'
22
+ end
23
+ }
24
+ let(:expected) { File.join(File.dirname(__FILE__), "checked.png") }
25
+
26
+ it 'matches checked.png when rendered' do
27
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
28
+ expect(pix_diff).to eq(0)
29
+ end
30
+ end
31
+ end
Binary file
@@ -0,0 +1,49 @@
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
+
3
+ describe 'a PDF with a checkbox group' do
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'nothing checked' do
7
+ let(:template) {
8
+ PDFRavager::Template.new
9
+ }
10
+ let(:expected) { File.join(File.dirname(__FILE__), "unchecked.png") }
11
+
12
+ it 'matches unchecked.png when rendered' do
13
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
14
+ expect(pix_diff).to eq(0)
15
+ end
16
+ end
17
+
18
+ context 'CheckBoxGroup.foo checked' do
19
+ let(:template) {
20
+ PDFRavager::Template.new do |t|
21
+ t.checkbox_group 'CheckBoxGroup' do |g|
22
+ g.check 'foo'
23
+ end
24
+ end
25
+ }
26
+ let(:expected) { File.join(File.dirname(__FILE__), "foo.png") }
27
+
28
+ it 'matches foo.png when rendered' do
29
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
30
+ expect(pix_diff).to eq(0)
31
+ end
32
+ end
33
+
34
+ context 'CheckBoxGroup.bar checked' do
35
+ let(:template) {
36
+ PDFRavager::Template.new do |t|
37
+ t.checkbox_group 'CheckBoxGroup' do |g|
38
+ g.check 'bar'
39
+ end
40
+ end
41
+ }
42
+ let(:expected) { File.join(File.dirname(__FILE__), "bar.png") }
43
+
44
+ it 'matches bar.png when rendered' do
45
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
46
+ expect(pix_diff).to eq(0)
47
+ end
48
+ end
49
+ end
@@ -1,12 +1,13 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
- require 'rspec'
3
- require 'pdf_ravager'
4
2
  require 'securerandom'
5
3
  require 'chunky_png'
6
4
  require 'tempfile'
7
5
 
8
6
  def mktemp(ext)
9
- Tempfile.new(['', ext]).path
7
+ f = Tempfile.new(['', ext])
8
+ (@@prevent_gc ||= []) << f # prevents file from getting deleted until all tests are done
9
+ f.close
10
+ f.path
10
11
  end
11
12
 
12
13
  def pdf_to_ps(pdf_file, out_file=nil)
@@ -25,6 +26,16 @@ def pdf_to_png(pdf_file)
25
26
  ps_to_png(pdf_to_ps(pdf_file))
26
27
  end
27
28
 
29
+ def ravage_to_temp_file(template, input_pdf)
30
+ file = mktemp('.pdf')
31
+ template.ravage input_pdf, :out_file => file
32
+ file
33
+ end
34
+
35
+ def compare_pdf_to_png(input_pdf, png)
36
+ png_diff(pdf_to_png(input_pdf), png)
37
+ end
38
+
28
39
  # code taken from http://jeffkreeftmeijer.com/2011/comparing-images-and-creating-image-diffs/
29
40
  def png_diff(img1, img2)
30
41
  images = [
@@ -1,20 +1,19 @@
1
1
  require File.dirname(__FILE__) + '/../integration_helper'
2
2
 
3
3
  describe 'a PDF with a multiline text field' do
4
- describe 'filled with FOO' do
5
- before(:each) do
6
- p = PDFRavager::Template.new do |t|
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'filled with FOO' do
7
+ let(:template) {
8
+ PDFRavager::Template.new do |t|
7
9
  t.text 'multilinetext', 'FOO' * 10000
8
10
  end
9
- pdf_file = File.join(File.dirname(__FILE__), "pdf")
10
- @pdf_file = mktemp('.pdf')
11
- @pdf = p.ravage pdf_file, :out_file => @pdf_file
12
- end
11
+ }
12
+ let(:expected) { File.join(File.dirname(__FILE__), "expected.png") }
13
13
 
14
- it 'should match expected.png when rendered' do
15
- png = pdf_to_png(@pdf_file)
16
- pix_diff, pct_diff = png_diff(png, File.join(File.dirname(__FILE__), "expected.png"))
17
- pix_diff.should == 0
14
+ it 'matches expected.png when rendered' do
15
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
16
+ expect(pix_diff).to eq(0)
18
17
  end
19
18
  end
20
19
  end
Binary file
Binary file
@@ -0,0 +1,45 @@
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
+
3
+ describe 'a PDF with a radio field' do
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'with nothing filled in' do
7
+ let(:template) {
8
+ PDFRavager::Template.new
9
+ }
10
+ let(:expected) { File.join(File.dirname(__FILE__), "empty.png") }
11
+
12
+ it 'matches empty.png when rendered' do
13
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
14
+ expect(pix_diff).to eq(0)
15
+ end
16
+ end
17
+
18
+ context 'with "Yes" filled in' do
19
+ let(:template) {
20
+ PDFRavager::Template.new do |t|
21
+ t.fill 'RadioButtonList', 'Yes'
22
+ end
23
+ }
24
+ let(:expected) { File.join(File.dirname(__FILE__), "yes.png") }
25
+
26
+ it 'matches yes.png when rendered' do
27
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
28
+ expect(pix_diff).to eq(0)
29
+ end
30
+ end
31
+
32
+ context 'with "No" filled in' do
33
+ let(:template) {
34
+ PDFRavager::Template.new do |t|
35
+ t.fill 'RadioButtonList', 'No'
36
+ end
37
+ }
38
+ let(:expected) { File.join(File.dirname(__FILE__), "no.png") }
39
+
40
+ it 'matches no.png when rendered' do
41
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
42
+ expect(pix_diff).to eq(0)
43
+ end
44
+ end
45
+ end
@@ -1,20 +1,19 @@
1
- require 'integration/integration_helper'
1
+ require File.dirname(__FILE__) + '/../integration_helper'
2
2
 
3
3
  describe 'a PDF with a text field' do
4
- describe 'filled with foo' do
5
- before(:each) do
6
- p = PDFRavager::Template.new do |t|
4
+ let(:input_pdf) { File.join(File.dirname(__FILE__), "pdf") }
5
+
6
+ context 'filled with foo' do
7
+ let(:template) {
8
+ PDFRavager::Template.new do |t|
7
9
  t.text 'text_field', 'foo'
8
10
  end
9
- pdf_file = File.join(File.dirname(__FILE__), "pdf")
10
- @pdf_file = mktemp('.pdf')
11
- @pdf = p.ravage pdf_file, :out_file => @pdf_file
12
- end
11
+ }
12
+ let(:expected) { File.join(File.dirname(__FILE__), "expected.png") }
13
13
 
14
- it 'should match expected.png when rendered' do
15
- png = pdf_to_png(@pdf_file)
16
- pix_diff, pct_diff = png_diff(png, File.join(File.dirname(__FILE__), "expected.png"))
17
- pix_diff.should be 0
14
+ it 'matches expected.png when rendered' do
15
+ pix_diff, _ = compare_pdf_to_png(ravage_to_temp_file(template, input_pdf), expected)
16
+ expect(pix_diff).to eq(0)
18
17
  end
19
18
  end
20
19
  end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,4 @@
1
- require 'turn/autorun'
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+ require 'rspec'
4
+ require 'pdf_ravager'
@@ -1,27 +1,36 @@
1
1
  require File.dirname(__FILE__) + '/fields_helper'
2
- require 'pdf_ravager/template'
3
2
 
4
- class TestCheckbox < MiniTest::Unit::TestCase
3
+ describe PDFRavager::Fields::Checkbox do
5
4
 
6
- def setup
7
- @checked = PDFRavager::Fields::Checkbox.new('checkbox1', true, :true_value => 'foo', :false_value => 'bar')
8
- @unchecked = PDFRavager::Fields::Checkbox.new('checkbox2', false, :true_value => 'foo', :false_value => 'bar')
9
- end
5
+ let(:checked) { PDFRavager::Fields::Checkbox.new('checkbox1', true, :true_value => 'foo', :false_value => 'bar') }
6
+ let(:unchecked) { PDFRavager::Fields::Checkbox.new('checkbox2', false, :true_value => 'foo', :false_value => 'bar') }
10
7
 
11
- def test_that_custom_checked_acro_form_value_is_set
12
- assert_equal @checked.acro_form_value, 'foo'
13
- end
8
+ context 'checked' do
9
+ context 'AcroForm value' do
10
+ it 'sets value properly' do
11
+ expect(checked.xfa_value).to eq('foo')
12
+ end
13
+ end
14
14
 
15
- def test_that_custom_checked_xfa_value_is_set
16
- assert_equal @checked.xfa_value, 'foo'
15
+ context 'XFA value' do
16
+ it 'sets value properly' do
17
+ expect(checked.xfa_value).to eq('foo')
18
+ end
19
+ end
17
20
  end
18
21
 
19
- def test_that_custom_unchecked_acro_form_value_is_set
20
- assert_equal @unchecked.acro_form_value, 'bar'
21
- end
22
+ context 'unchecked' do
23
+ context 'AcroForm value' do
24
+ it 'sets value properly' do
25
+ expect(unchecked.xfa_value).to eq('bar')
26
+ end
27
+ end
22
28
 
23
- def test_that_custom_unchecked_xfa_value_is_set
24
- assert_equal @unchecked.xfa_value, 'bar'
29
+ context 'XFA value' do
30
+ it 'sets value properly' do
31
+ expect(unchecked.xfa_value).to eq('bar')
32
+ end
33
+ end
25
34
  end
26
35
 
27
36
  end
@@ -1,27 +1,33 @@
1
1
  require File.dirname(__FILE__) + '/unit_helper'
2
2
  require 'pdf_ravager/kernel'
3
3
 
4
- class TestKernelIntegration < MiniTest::Unit::TestCase
5
-
6
- def setup
7
- @template = pdf do |p|
4
+ describe Kernel do
5
+ let(:template) {
6
+ pdf do |p|
8
7
  p.text 'text', 'foo'
9
8
  p.rich_text 'rich_text', '<b>foo</b>'
10
9
  p.check 'checkbox1'
11
10
  p.uncheck 'checkbox2'
12
11
  p.fill 'radio_group', 'button'
13
12
  end
14
- end
13
+ }
15
14
 
16
- def test_that_dsl_template_equals_longform_template
17
- template = PDFRavager::Template.new do |t|
15
+ let(:longform_template) {
16
+ PDFRavager::Template.new do |t|
18
17
  t.text 'text', 'foo'
19
18
  t.rich_text 'rich_text', '<b>foo</b>'
20
19
  t.check 'checkbox1'
21
20
  t.uncheck 'checkbox2'
22
21
  t.fill 'radio_group', 'button'
23
22
  end
24
- assert_equal @template, template
23
+ }
24
+
25
+ context 'equality' do
26
+ context 'a shorthand and longform template with equal options' do
27
+ it 'is equal' do
28
+ expect(template).to eq(longform_template)
29
+ end
30
+ end
25
31
  end
26
32
 
27
33
  end
@@ -1,61 +1,111 @@
1
1
  require File.dirname(__FILE__) + '/unit_helper'
2
- require 'pdf_ravager/template'
3
2
 
4
- class TestTemplate < MiniTest::Unit::TestCase
3
+ describe PDFRavager::Template do
5
4
 
6
- def setup
7
- @template = PDFRavager::Template.new do |t|
8
- t.text 'text', 'foo'
9
- t.rich_text 'rich_text', '<b>foo</b>'
10
- t.check 'checkbox1'
11
- t.uncheck 'checkbox2'
12
- t.checkbox_group 'cbox_group' do |cb|
13
- cb.check 'checked'
14
- cb.uncheck 'unchecked'
5
+ context 'initialization' do
6
+ context 'template with a name' do
7
+ let(:template) { PDFRavager::Template.new('template') }
8
+
9
+ it 'sets the name' do
10
+ expect(template.name).to eq('template')
15
11
  end
16
- t.fill 'radio_group', 'button'
17
- t.radio_group 'better_radio_group' do |rg|
18
- rg.fill 'button'
12
+ end
13
+
14
+ context 'template without a name' do
15
+ let(:template) { PDFRavager::Template.new }
16
+
17
+ it 'does not set the name' do
18
+ expect(template.name).to be_nil
19
19
  end
20
20
  end
21
21
 
22
- @template_with_name = PDFRavager::Template.new('template'){}
23
- end
22
+ context 'setting strategy' do
23
+ context 'with a valid strategy' do
24
+ let(:template) { PDFRavager::Template.new(:strategy => :xfa) }
24
25
 
25
- def test_that_text_is_set
26
- assert_includes @template.fields, PDFRavager::Fields::Text.new('text', 'foo')
27
- end
26
+ it 'sets the strategy' do
27
+ expect(template.strategy).to eq(:xfa)
28
+ end
29
+ end
28
30
 
29
- def test_that_rich_text_is_set
30
- assert_includes @template.fields, PDFRavager::Fields::RichText.new('rich_text', '<b>foo</b>')
31
+ context 'with an invalid strategy' do
32
+ it 'raises an error' do
33
+ expect { PDFRavager::Template.new(:strategy => :foo) }.to raise_error
34
+ end
35
+ end
36
+ end
31
37
  end
32
38
 
33
- def test_that_checkbox_is_set
34
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('checkbox1', true)
35
- end
39
+ context 'setting template values' do
36
40
 
37
- def test_that_checkbox_is_unset
38
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('checkbox2', false)
39
- end
41
+ let(:template) {
42
+ PDFRavager::Template.new do |t|
43
+ t.text 'text', 'foo'
44
+ t.rich_text 'rich_text', '<b>foo</b>'
45
+ t.check 'checkbox1'
46
+ t.uncheck 'checkbox2'
47
+ t.checkbox_group 'cbox_group' do |cb|
48
+ cb.check 'checked'
49
+ cb.uncheck 'unchecked'
50
+ end
51
+ t.fill 'radio_group', 'button'
52
+ t.radio_group 'better_radio_group' do |rg|
53
+ rg.fill 'button'
54
+ end
55
+ end
56
+ }
40
57
 
41
- def test_that_radio_button_is_filled
42
- assert_includes @template.fields, PDFRavager::Fields::Radio.new('radio_group', 'button')
43
- end
58
+ context 'text' do
59
+ it 'is set' do
60
+ expect(template.fields).to include(PDFRavager::Fields::Text.new('text', 'foo'))
61
+ end
62
+ end
44
63
 
45
- def test_that_name_is_set
46
- assert_equal @template_with_name.name, 'template'
47
- end
64
+ context 'rich_text' do
65
+ it 'is set' do
66
+ expect(template.fields).to include(PDFRavager::Fields::RichText.new('rich_text', '<b>foo</b>'))
67
+ end
68
+ end
48
69
 
49
- def test_that_checkbox_group_box_is_checked
50
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('cbox_group.checked', true)
51
- end
70
+ context 'checkbox1' do
71
+ it 'is set' do
72
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('checkbox1', true))
73
+ end
74
+ end
52
75
 
53
- def test_that_checkbox_group_box_is_unchecked
54
- assert_includes @template.fields, PDFRavager::Fields::Checkbox.new('cbox_group.unchecked', false)
55
- end
76
+ context 'checkbox2' do
77
+ it 'is unset' do
78
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('checkbox2', false))
79
+ end
80
+ end
81
+
82
+ context 'cbox_group' do
83
+ context '.checked' do
84
+ it 'is checked' do
85
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('cbox_group.checked', true))
86
+ end
87
+ end
88
+
89
+ context '.unchecked' do
90
+ it 'is unchecked' do
91
+ expect(template.fields).to include(PDFRavager::Fields::Checkbox.new('cbox_group.unchecked', false))
92
+ end
93
+ end
94
+ end
56
95
 
57
- def test_that_radio_group_button_is_filled
58
- assert_includes @template.fields, PDFRavager::Fields::Radio.new('better_radio_group', 'button')
96
+ context 'radio buttons' do
97
+ context 'one-line syntax' do
98
+ it 'fills the radio_group button' do
99
+ expect(template.fields).to include(PDFRavager::Fields::Radio.new('radio_group', 'button'))
100
+ end
101
+ end
102
+
103
+ context 'block syntax' do
104
+ it 'fills the better_radio_group button' do
105
+ expect(template.fields).to include(PDFRavager::Fields::Radio.new('better_radio_group', 'button'))
106
+ end
107
+ end
108
+ end
59
109
  end
60
110
 
61
111
  end
@@ -1,2 +1,2 @@
1
1
  require File.dirname(__FILE__) + '/../spec_helper'
2
- require 'minitest/autorun'
2
+ require 'rspec/autorun'
metadata CHANGED
@@ -1,122 +1,95 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdf_ravager
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
5
- prerelease:
4
+ version: 0.2.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Abe Voelker
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-05-10 00:00:00.000000000 Z
11
+ date: 2014-03-31 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: nokogiri
16
15
  version_requirements: !ruby/object:Gem::Requirement
17
16
  requirements:
18
- - - ">="
17
+ - - '>='
19
18
  - !ruby/object:Gem::Version
20
- version: !binary |-
21
- MA==
22
- none: false
19
+ version: '0'
23
20
  requirement: !ruby/object:Gem::Requirement
24
21
  requirements:
25
- - - ">="
22
+ - - '>='
26
23
  - !ruby/object:Gem::Version
27
- version: !binary |-
28
- MA==
29
- none: false
24
+ version: '0'
30
25
  prerelease: false
31
26
  type: :runtime
32
27
  - !ruby/object:Gem::Dependency
33
28
  name: bundler
34
29
  version_requirements: !ruby/object:Gem::Requirement
35
30
  requirements:
36
- - - "~>"
31
+ - - ~>
37
32
  - !ruby/object:Gem::Version
38
33
  version: '1.0'
39
- none: false
40
34
  requirement: !ruby/object:Gem::Requirement
41
35
  requirements:
42
- - - "~>"
36
+ - - ~>
43
37
  - !ruby/object:Gem::Version
44
38
  version: '1.0'
45
- none: false
46
- prerelease: false
47
- type: :development
48
- - !ruby/object:Gem::Dependency
49
- name: minitest
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '4.1'
55
- none: false
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '4.1'
61
- none: false
62
39
  prerelease: false
63
40
  type: :development
64
41
  - !ruby/object:Gem::Dependency
65
42
  name: rspec
66
43
  version_requirements: !ruby/object:Gem::Requirement
67
44
  requirements:
68
- - - "~>"
45
+ - - ~>
69
46
  - !ruby/object:Gem::Version
70
47
  version: '2.11'
71
- none: false
72
48
  requirement: !ruby/object:Gem::Requirement
73
49
  requirements:
74
- - - "~>"
50
+ - - ~>
75
51
  - !ruby/object:Gem::Version
76
52
  version: '2.11'
77
- none: false
78
53
  prerelease: false
79
54
  type: :development
80
55
  - !ruby/object:Gem::Dependency
81
56
  name: rake
82
57
  version_requirements: !ruby/object:Gem::Requirement
83
58
  requirements:
84
- - - "~>"
59
+ - - ~>
85
60
  - !ruby/object:Gem::Version
86
61
  version: '0.9'
87
- none: false
88
62
  requirement: !ruby/object:Gem::Requirement
89
63
  requirements:
90
- - - "~>"
64
+ - - ~>
91
65
  - !ruby/object:Gem::Version
92
66
  version: '0.9'
93
- none: false
94
67
  prerelease: false
95
68
  type: :development
96
69
  - !ruby/object:Gem::Dependency
97
70
  name: chunky_png
98
71
  version_requirements: !ruby/object:Gem::Requirement
99
72
  requirements:
100
- - - "~>"
73
+ - - ~>
101
74
  - !ruby/object:Gem::Version
102
75
  version: '1.2'
103
- none: false
104
76
  requirement: !ruby/object:Gem::Requirement
105
77
  requirements:
106
- - - "~>"
78
+ - - ~>
107
79
  - !ruby/object:Gem::Version
108
80
  version: '1.2'
109
- none: false
110
81
  prerelease: false
111
82
  type: :development
112
- description: DSL to aid filling out AcroForms PDF and XFA documents
83
+ description: JRuby-only DSL for filling out AcroForms PDF and XFA documents
113
84
  email: abe@abevoelker.com
114
85
  executables: []
115
86
  extensions: []
116
87
  extra_rdoc_files: []
117
88
  files:
118
- - ".gitignore"
119
- - ".travis.yml"
89
+ - .gitignore
90
+ - .rspec
91
+ - .travis.yml
92
+ - CHANGELOG.md
120
93
  - Gemfile
121
94
  - LICENSE
122
95
  - README.md
@@ -132,13 +105,30 @@ files:
132
105
  - lib/pdf_ravager/fieldsets/radio_group.rb
133
106
  - lib/pdf_ravager/kernel.rb
134
107
  - lib/pdf_ravager/ravager.rb
108
+ - lib/pdf_ravager/strategies/acro_form.rb
109
+ - lib/pdf_ravager/strategies/smart.rb
110
+ - lib/pdf_ravager/strategies/xfa.rb
135
111
  - lib/pdf_ravager/template.rb
136
112
  - lib/pdf_ravager/version.rb
137
113
  - pdf_ravager.gemspec
114
+ - spec/integration/checkbox_field/checked.png
115
+ - spec/integration/checkbox_field/pdf
116
+ - spec/integration/checkbox_field/spec.rb
117
+ - spec/integration/checkbox_field/unchecked.png
118
+ - spec/integration/checkbox_group/bar.png
119
+ - spec/integration/checkbox_group/foo.png
120
+ - spec/integration/checkbox_group/pdf
121
+ - spec/integration/checkbox_group/spec.rb
122
+ - spec/integration/checkbox_group/unchecked.png
138
123
  - spec/integration/integration_helper.rb
139
124
  - spec/integration/multiline_text_field/expected.png
140
125
  - spec/integration/multiline_text_field/pdf
141
126
  - spec/integration/multiline_text_field/spec.rb
127
+ - spec/integration/radio_field/empty.png
128
+ - spec/integration/radio_field/no.png
129
+ - spec/integration/radio_field/pdf
130
+ - spec/integration/radio_field/spec.rb
131
+ - spec/integration/radio_field/yes.png
142
132
  - spec/integration/text_field/expected.png
143
133
  - spec/integration/text_field/pdf
144
134
  - spec/integration/text_field/spec.rb
@@ -152,41 +142,46 @@ files:
152
142
  homepage: https://github.com/abevoelker/pdf_ravager
153
143
  licenses:
154
144
  - MIT
145
+ metadata: {}
155
146
  post_install_message:
156
147
  rdoc_options: []
157
148
  require_paths:
158
149
  - lib
159
150
  required_ruby_version: !ruby/object:Gem::Requirement
160
151
  requirements:
161
- - - ">="
152
+ - - '>='
162
153
  - !ruby/object:Gem::Version
163
- segments:
164
- - 0
165
- version: !binary |-
166
- MA==
167
- hash: 2
168
- none: false
154
+ version: '0'
169
155
  required_rubygems_version: !ruby/object:Gem::Requirement
170
156
  requirements:
171
- - - ">="
157
+ - - '>='
172
158
  - !ruby/object:Gem::Version
173
- segments:
174
- - 0
175
- version: !binary |-
176
- MA==
177
- hash: 2
178
- none: false
159
+ version: '0'
179
160
  requirements: []
180
161
  rubyforge_project:
181
- rubygems_version: 1.8.24
162
+ rubygems_version: 2.1.9
182
163
  signing_key:
183
- specification_version: 3
184
- summary: DSL to aid filling out AcroForms PDF and XFA documents
164
+ specification_version: 4
165
+ summary: JRuby-only DSL for filling out AcroForms PDF and XFA documents
185
166
  test_files:
167
+ - spec/integration/checkbox_field/checked.png
168
+ - spec/integration/checkbox_field/pdf
169
+ - spec/integration/checkbox_field/spec.rb
170
+ - spec/integration/checkbox_field/unchecked.png
171
+ - spec/integration/checkbox_group/bar.png
172
+ - spec/integration/checkbox_group/foo.png
173
+ - spec/integration/checkbox_group/pdf
174
+ - spec/integration/checkbox_group/spec.rb
175
+ - spec/integration/checkbox_group/unchecked.png
186
176
  - spec/integration/integration_helper.rb
187
177
  - spec/integration/multiline_text_field/expected.png
188
178
  - spec/integration/multiline_text_field/pdf
189
179
  - spec/integration/multiline_text_field/spec.rb
180
+ - spec/integration/radio_field/empty.png
181
+ - spec/integration/radio_field/no.png
182
+ - spec/integration/radio_field/pdf
183
+ - spec/integration/radio_field/spec.rb
184
+ - spec/integration/radio_field/yes.png
190
185
  - spec/integration/text_field/expected.png
191
186
  - spec/integration/text_field/pdf
192
187
  - spec/integration/text_field/spec.rb