odf-report 0.5.2 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/gem-push.yml +40 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +62 -0
  5. data/README.md +220 -0
  6. data/bin/odt-extract +10 -0
  7. data/bin/odt-viewer +18 -0
  8. data/lib/odf-report.rb +11 -8
  9. data/lib/odf-report/data_source.rb +65 -0
  10. data/lib/odf-report/field.rb +7 -40
  11. data/lib/odf-report/image.rb +57 -0
  12. data/lib/odf-report/nestable.rb +65 -0
  13. data/lib/odf-report/report.rb +24 -28
  14. data/lib/odf-report/section.rb +15 -42
  15. data/lib/odf-report/table.rb +54 -59
  16. data/lib/odf-report/template.rb +88 -0
  17. data/lib/odf-report/text.rb +1 -3
  18. data/lib/odf-report/version.rb +1 -1
  19. data/odf-report.gemspec +4 -4
  20. data/spec/fields_spec.rb +4 -4
  21. data/spec/images/image_1.jpg +0 -0
  22. data/spec/images/image_2.jpg +0 -0
  23. data/spec/images/image_3.jpg +0 -0
  24. data/spec/images/piriapolis.jpg +0 -0
  25. data/spec/images/placeholder.jpg +0 -0
  26. data/spec/images/rails.png +0 -0
  27. data/spec/images_spec.rb +159 -0
  28. data/spec/sections_spec.rb +51 -0
  29. data/spec/spec_helper.rb +2 -4
  30. data/spec/tables_spec.rb +1 -1
  31. data/spec/template_spec.rb +45 -0
  32. data/spec/templates/images.odt +0 -0
  33. data/spec/templates/specs.odt +0 -0
  34. data/test/images_test.rb +32 -0
  35. data/test/templates/images/image_1.jpg +0 -0
  36. data/test/templates/images/image_2.jpg +0 -0
  37. data/test/templates/images/image_3.jpg +0 -0
  38. data/test/templates/images/placeholder.jpg +0 -0
  39. data/test/templates/images/placeholder.png +0 -0
  40. data/test/templates/test_images.odt +0 -0
  41. data/test/test.rb +262 -0
  42. metadata +77 -23
  43. data/README.textile +0 -223
  44. data/lib/odf-report/file.rb +0 -50
  45. data/lib/odf-report/images.rb +0 -44
  46. data/lib/odf-report/nested.rb +0 -62
  47. data/spec/specs.odt +0 -0
@@ -0,0 +1,88 @@
1
+ module ODFReport
2
+ class Template
3
+
4
+ CONTENT_FILES = ['content.xml', 'styles.xml']
5
+ MANIFEST_FILE = "META-INF/manifest.xml"
6
+
7
+ attr_accessor :output_stream
8
+
9
+ def initialize(template = nil, io: nil)
10
+ raise "You must provide either a filename or an io: string" unless template || io
11
+ raise "Template [#{template}] not found." unless template.nil? || ::File.exist?(template)
12
+
13
+ @template = template
14
+ @io = io
15
+ end
16
+
17
+ def update_content
18
+ @buffer = Zip::OutputStream.write_buffer do |out|
19
+ @output_stream = out
20
+ yield self
21
+ end
22
+ end
23
+
24
+ def update_files(&block)
25
+
26
+ get_template_entries.each do |entry|
27
+
28
+ next if entry.directory?
29
+
30
+ entry.get_input_stream do |is|
31
+
32
+ data = is.sysread
33
+
34
+ if CONTENT_FILES.include?(entry.name)
35
+ process_entry(data, &block)
36
+ end
37
+
38
+ update_file(entry.name, data) unless entry.name == MANIFEST_FILE
39
+
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ def update_manifest(&block)
46
+ entry = get_template_entries.find_entry(MANIFEST_FILE)
47
+
48
+ entry.get_input_stream do |is|
49
+
50
+ data = is.sysread
51
+
52
+ process_entry(data, &block)
53
+
54
+ update_file(MANIFEST_FILE, data)
55
+
56
+ end
57
+
58
+ end
59
+
60
+ def data
61
+ @buffer.string
62
+ end
63
+
64
+ def update_file(name, data)
65
+ @output_stream.put_next_entry(name)
66
+ @output_stream.write data
67
+ end
68
+
69
+ private
70
+
71
+ def get_template_entries
72
+
73
+ if @template
74
+ Zip::File.open(@template)
75
+ else
76
+ Zip::File.open_buffer(@io.force_encoding("ASCII-8BIT"))
77
+ end
78
+
79
+ end
80
+
81
+ def process_entry(entry)
82
+ doc = Nokogiri::XML(entry, &:noblanks)
83
+ yield doc
84
+ entry.replace(doc.to_xml(save_with: Nokogiri::XML::Node::SaveOptions::AS_XML))
85
+ end
86
+
87
+ end
88
+ end
@@ -8,9 +8,7 @@ module ODFReport
8
8
 
9
9
  return unless node = find_text_node(doc)
10
10
 
11
- text_value = get_value(data_item)
12
-
13
- @parser = Parser::Default.new(text_value, node)
11
+ @parser = Parser::Default.new(@data_source.value, node)
14
12
 
15
13
  @parser.paragraphs.each do |p|
16
14
  node.before(p)
@@ -1,3 +1,3 @@
1
1
  module ODFReport
2
- VERSION = "0.5.2"
2
+ VERSION = "0.7.2"
3
3
  end
@@ -9,7 +9,6 @@ Gem::Specification.new do |s|
9
9
  s.authors = ["Sandro Duarte"]
10
10
  s.description = %q{Generates ODF files, given a template (.odt) and data, replacing tags}
11
11
  s.email = %q{sandrods@gmail.com}
12
- s.has_rdoc = false
13
12
  s.homepage = %q{http://sandrods.github.com/odf-report/}
14
13
  s.rubygems_version = %q{1.3.7}
15
14
  s.summary = %q{Generates ODF files, given a template (.odt) and data, replacing tags}
@@ -19,13 +18,14 @@ Gem::Specification.new do |s|
19
18
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
20
19
  s.require_paths = ["lib"]
21
20
 
22
- s.add_development_dependency "bundler", "~> 1.6"
21
+ s.add_development_dependency "bundler"
23
22
  s.add_development_dependency "rake"
24
23
  s.add_development_dependency "rspec", "~> 3.0.0"
25
24
  s.add_development_dependency "faker"
26
25
  s.add_development_dependency "launchy"
27
26
 
28
- s.add_runtime_dependency('rubyzip', "~> 1.2.0")
29
- s.add_runtime_dependency('nokogiri', ">= 1.5.0")
27
+ s.add_runtime_dependency('rubyzip', ">= 1.3.0")
28
+ s.add_runtime_dependency('nokogiri', ">= 1.10.0")
29
+ s.add_runtime_dependency('mime-types')
30
30
 
31
31
  end
@@ -7,7 +7,7 @@ RSpec.describe "Fields" do
7
7
 
8
8
  @itens_01 = Item.get_list(3)
9
9
 
10
- report = ODFReport::Report.new("spec/specs.odt") do |r|
10
+ report = ODFReport::Report.new("spec/templates/specs.odt") do |r|
11
11
 
12
12
  r.add_field(:field_01, @field_01)
13
13
  r.add_field(:field_02, @field_02)
@@ -51,7 +51,7 @@ RSpec.describe "Fields" do
51
51
  expect(table).not_to match(/\[COLUMN_02\]/)
52
52
  expect(table).to match(/\[COLUMN_03\]/)
53
53
 
54
- expect(table).to match(item.id)
54
+ expect(table).to match(item.id.to_s)
55
55
  expect(table).to match(item.name)
56
56
 
57
57
  end
@@ -65,9 +65,9 @@ RSpec.describe "Fields" do
65
65
 
66
66
  @itens_01.each_with_index do |item, idx|
67
67
 
68
- section = @data.xml.xpath(".//text:section[@text:name='SECTION_01_#{idx+1}']").to_s
68
+ section = @data.xml.at_xpath(".//text:section[#{idx+1}]").to_s
69
69
 
70
- expect(section).to match(item.id)
70
+ expect(section).to match(item.id.to_s)
71
71
  expect(section).to match(item.name)
72
72
 
73
73
  end
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,159 @@
1
+ RSpec.describe "Images" do
2
+
3
+ context('Adding Images') do
4
+
5
+ before(:context) do
6
+
7
+ @list = []
8
+ @list << OpenStruct.new({ name: "IMG - [1, 1]", path: 'spec/images/image_1.jpg', path2: 'spec/images/image_1.jpg' })
9
+ @list << OpenStruct.new({ name: "IMG - [2, 1]", path: 'spec/images/image_2.jpg', path2: 'spec/images/image_1.jpg' })
10
+ @list << OpenStruct.new({ name: "IMG - [3, 2]", path: 'spec/images/image_3.jpg', path2: 'spec/images/image_2.jpg' })
11
+ @list << OpenStruct.new({ name: "IMG - [1, 3]", path: 'spec/images/image_1.jpg', path2: 'spec/images/image_3.jpg' })
12
+ @list << OpenStruct.new({ name: "IMG - [2, 2]", path: 'spec/images/image_2.jpg', path2: 'spec/images/image_2.jpg' })
13
+
14
+
15
+ report = ODFReport::Report.new("spec/templates/images.odt") do |r|
16
+
17
+ r.add_image("IMAGE_01", 'spec/images/rails.png')
18
+ r.add_image("IMAGE_02", 'spec/images/piriapolis.jpg')
19
+
20
+ r.add_table('IMAGE_TABLE', @list) do |t|
21
+ t.add_column(:image_name, :name)
22
+ t.add_image('IMAGE_IN_TABLE_01', :path)
23
+ t.add_image('IMAGE_IN_TABLE_02', :path2)
24
+ end
25
+
26
+ r.add_section('SECTION', @list) do |t|
27
+ t.add_field(:image_name, :name)
28
+ t.add_image('IMAGE_IN_SECTION_01', :path2)
29
+ t.add_image('IMAGE_IN_SECTION_02', :path)
30
+ end
31
+
32
+ end
33
+
34
+ report.generate("spec/result/images.odt")
35
+
36
+ @data = Inspector.new("spec/result/images.odt")
37
+
38
+ end
39
+
40
+
41
+ it "simple image replacement" do
42
+
43
+ images = @data.xml.xpath("//draw:image")
44
+
45
+ expect(images[0].attribute('href').value).to eq "Pictures/rails.png"
46
+ expect(images[1].attribute('href').value).to eq "Pictures/piriapolis.jpg"
47
+
48
+ end
49
+
50
+ it "table columns replacement" do
51
+
52
+ table = @data.xml.at_xpath(".//table:table[@table:name='IMAGE_TABLE']")
53
+
54
+ @list.each_with_index do |item, idx|
55
+
56
+ row = table.xpath(".//table:table-row[#{idx+1}]")
57
+
58
+ images = row.xpath(".//draw:image")
59
+
60
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(item.path)
61
+ expect(File.basename(images[1].attribute('href').value)).to eq File.basename(item.path2)
62
+
63
+ end
64
+
65
+ end
66
+
67
+ it "section fields replacement" do
68
+
69
+ @list.each_with_index do |item, idx|
70
+
71
+ section = @data.xml.at_xpath(".//text:section[#{idx+1}]")
72
+
73
+ images = section.xpath(".//draw:image")
74
+
75
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(item.path)
76
+ expect(File.basename(images[1].attribute('href').value)).to eq File.basename(item.path2)
77
+
78
+ end
79
+
80
+ end
81
+ end
82
+
83
+ context "Removing Images" do
84
+
85
+ before(:context) do
86
+
87
+ @list = []
88
+ @list << OpenStruct.new({ name: "IMG - both ok", path: 'spec/images/image_1.jpg', path2: 'spec/images/image_1.jpg' })
89
+ @list << OpenStruct.new({ name: "IMG - 1 ok", path: 'spec/images/image_2.jpg', path2: nil })
90
+ @list << OpenStruct.new({ name: "IMG - 2 ok", path: nil, path2: 'spec/images/image_3.jpg' })
91
+ # @list << OpenStruct.new({ name: "IMG - 2 invalid", path: nil, path2: 'spec/images/invalid.jpg' })
92
+
93
+ report = ODFReport::Report.new("spec/templates/images.odt") do |r|
94
+
95
+ # r.add_image("IMAGE_01")
96
+ r.add_image("IMAGE_02", nil)
97
+
98
+ r.add_table('IMAGE_TABLE', @list) do |t|
99
+ t.add_column(:image_name, :name)
100
+ t.add_image('IMAGE_IN_TABLE_01', :path)
101
+ t.add_image('IMAGE_IN_TABLE_02', :path2)
102
+ end
103
+
104
+ r.add_section('SECTION', @list) do |t|
105
+ t.add_field(:image_name, :name)
106
+ t.add_image('IMAGE_IN_SECTION_01', :path2)
107
+ t.add_image('IMAGE_IN_SECTION_02', :path)
108
+ end
109
+
110
+ end
111
+
112
+ report.generate("spec/result/images.odt")
113
+
114
+ @data = Inspector.new("spec/result/images.odt")
115
+
116
+ end
117
+
118
+ it "removes nil images in report" do
119
+ expect(@data.xml.at_css("draw|frame[@draw|name='IMAGE_01']")).to be
120
+ expect(@data.xml.at_css("draw|frame[@draw|name='IMAGE_02']")).to be_nil
121
+ end
122
+
123
+ it "removes nil images in tables" do
124
+
125
+ table = @data.xml.at_xpath(".//table:table[@table:name='IMAGE_TABLE']")
126
+
127
+ images = table.xpath(".//table:table-row[1]//draw:image")
128
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(@list[0].path)
129
+ expect(File.basename(images[1].attribute('href').value)).to eq File.basename(@list[0].path2)
130
+
131
+ images = table.xpath(".//table:table-row[2]//draw:image")
132
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(@list[1].path)
133
+ expect(images[1]).to be_nil
134
+
135
+ images = table.xpath(".//table:table-row[3]//draw:image")
136
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(@list[2].path2)
137
+ expect(images[1]).to be_nil
138
+
139
+ end
140
+
141
+ it "removes nil images in sections " do
142
+
143
+ images = @data.xml.xpath(".//text:section[1]//draw:image")
144
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(@list[0].path)
145
+ expect(File.basename(images[1].attribute('href').value)).to eq File.basename(@list[0].path2)
146
+
147
+ images = @data.xml.xpath(".//text:section[2]//draw:image")
148
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(@list[1].path)
149
+ expect(images[1]).to be_nil
150
+
151
+ images = @data.xml.xpath(".//text:section[3]//draw:image")
152
+ expect(File.basename(images[0].attribute('href').value)).to eq File.basename(@list[2].path2)
153
+ expect(images[1]).to be_nil
154
+
155
+ end
156
+
157
+ end
158
+
159
+ end
@@ -0,0 +1,51 @@
1
+ RSpec.describe "Sections" do
2
+
3
+ before(:context) do
4
+ @itens = Item.get_list(3)
5
+
6
+ report = ODFReport::Report.new("spec/templates/specs.odt") do |r|
7
+
8
+ r.add_section('SECTION_01', @itens) do |t|
9
+ t.add_field(:s01_field_01, :id)
10
+ t.add_field(:s01_field_02, :name)
11
+ end
12
+
13
+ r.add_section('SECTION_02', []) do |t|
14
+ t.add_field(:s02_field_01, :id)
15
+ t.add_field(:s02_field_02, :name)
16
+ end
17
+
18
+ r.add_section('SECTION_03', nil) do |t|
19
+ t.add_field(:s03_field_01, :id)
20
+ t.add_field(:s03_field_02, :name)
21
+ end
22
+
23
+ end
24
+
25
+ report.generate("spec/result/specs.odt")
26
+
27
+ @data = Inspector.new("spec/result/specs.odt")
28
+
29
+ end
30
+
31
+ it "should render section with collection" do
32
+ @itens.each_with_index do |item, idx|
33
+ section = @data.xml.at_xpath(".//text:section[#{idx+1}]").to_s
34
+
35
+ expect(section).to match(item.id.to_s)
36
+ expect(section).to match(item.name)
37
+ end
38
+ end
39
+
40
+ it "should remove section with empty collection" do
41
+ section = @data.xml.at_css("text|section[@text|name='SECTION_02']")
42
+ expect(section).to be_nil
43
+ end
44
+
45
+ it "should remove section with nil collection" do
46
+ section = @data.xml.at_css("text|section[@text|name='SECTION_03']")
47
+ expect(section).to be_nil
48
+ end
49
+
50
+
51
+ end
@@ -12,11 +12,9 @@ class Item
12
12
  end
13
13
 
14
14
  def self.get_list(quant = 3)
15
- r = []
16
- (1..quant).each do |i|
17
- r << Item.new(Faker::Number.number(10), Faker::Name.name)
15
+ (1..quant).map do |i|
16
+ Item.new(Faker::Number.number(digits: 10), Faker::Name.name)
18
17
  end
19
- r
20
18
  end
21
19
 
22
20
  end
@@ -2,7 +2,7 @@ RSpec.describe "Tables" do
2
2
 
3
3
  before(:context) do
4
4
 
5
- report = ODFReport::Report.new("spec/specs.odt") do |r|
5
+ report = ODFReport::Report.new("spec/templates/specs.odt") do |r|
6
6
 
7
7
  r.add_table('TABLE_02', []) do |t|
8
8
  t.add_column(:column_01, :id)
@@ -0,0 +1,45 @@
1
+ RSpec.describe "Templates Types" do
2
+
3
+ before(:each) do
4
+
5
+ @field_01 = Faker::Company.name
6
+ @field_02 = Faker::Name.name
7
+
8
+ report.add_field(:field_01, @field_01)
9
+ report.add_field(:field_02, @field_02)
10
+
11
+ report.generate("spec/result/specs.odt")
12
+
13
+ @data = Inspector.new("spec/result/specs.odt")
14
+
15
+ end
16
+
17
+ context "template from file" do
18
+ let(:report) { ODFReport::Report.new("spec/templates/specs.odt") }
19
+
20
+ it "works" do
21
+
22
+ expect(@data.text).not_to match(/\[FIELD_01\]/)
23
+ expect(@data.text).not_to match(/\[FIELD_02\]/)
24
+
25
+ expect(@data.text).to match @field_01
26
+ expect(@data.text).to match @field_02
27
+
28
+ end
29
+ end
30
+
31
+ context "template from a String" do
32
+ let(:report) { ODFReport::Report.new(io: File.open("spec/templates/specs.odt").read) }
33
+
34
+ it "works" do
35
+
36
+ expect(@data.text).not_to match(/\[FIELD_01\]/)
37
+ expect(@data.text).not_to match(/\[FIELD_02\]/)
38
+
39
+ expect(@data.text).to match @field_01
40
+ expect(@data.text).to match @field_02
41
+
42
+ end
43
+ end
44
+
45
+ end