odf-report 0.3.3 → 0.4.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.
@@ -3,11 +3,20 @@ h1. ODF-REPORT
3
3
  Gem for generating .odt files by making strings, images, tables and sections replacements in a previously created .odt file.
4
4
 
5
5
 
6
+ h2. NEW!
7
+
8
+ <pre>
9
+ ODF-REPORT have been internally refactored. It now uses Nokogiri for parsing the documents, instead of Regex.
10
+
11
+ This provides for a much greater flexibility. As a result, I was able to implement nested sections.
12
+
13
+ Now sections can be nested inside sections, with fields, tables and others sections.
14
+ </pre>
15
+
6
16
  h2. INSTALL
7
17
 
8
18
  (sudo) gem install odf-report
9
19
 
10
-
11
20
  h2. USAGE
12
21
 
13
22
  h3. Step 1 -- the template
@@ -96,11 +105,11 @@ end
96
105
  </pre>
97
106
 
98
107
 
99
- h3. Sections (NEW!)
108
+ h3. Sections
100
109
 
101
110
  Sometimes, you have to repeat a whole chunk of a document, in a structure a lot more complex than a table. Now you can make a Section in your template and use it in this situations. Creating a Session in OpenOffice is as easy as select menu *Insert* and then *Section...*, and then choose a name for it.
102
111
 
103
- *Section* 's are lot like Tables, in the sense that you can pass a collection and have that section repeated for each member of the collection. *But*, Sections can have anything inside it, even Tables, as long as you pass the appropriate data structure.
112
+ *Section* 's are lot like Tables, in the sense that you can pass a collection and have that section repeated for each member of the collection. *But*, Sections can have anything inside it, even Tables *and nested Sections*, as long as you pass the appropriate data structure.
104
113
 
105
114
  Let's see an example:
106
115
 
@@ -133,6 +142,14 @@ Let's see an example:
133
142
  end
134
143
  end
135
144
 
145
+ s.add_section("SUB_NOTES", :notes) do |s1|
146
+
147
+ s1.add_field(:note_title) { |n| n.title }
148
+
149
+ s1.add_table ...
150
+
151
+ end
152
+
136
153
  end
137
154
 
138
155
  end
@@ -208,6 +225,7 @@ report.generate("./documents/")
208
225
  h3. REQUIREMENTS
209
226
 
210
227
  *rubyzip*: for manipulating the contents of the odt file, since it's actually a zip file.
228
+ *nokogiri*: for parsing and manipulating the document xml files.
211
229
 
212
230
 
213
231
  <hr/>
@@ -1,8 +1,12 @@
1
1
  require 'rubygems'
2
2
  require 'zip/zipfilesystem'
3
3
  require 'fileutils'
4
- require File.expand_path('../odf-report/file_ops',__FILE__)
5
- require File.expand_path('../odf-report/hash_gsub',__FILE__)
6
- require File.expand_path('../odf-report/section',__FILE__)
7
- require File.expand_path('../odf-report/table',__FILE__)
8
- require File.expand_path('../odf-report/report',__FILE__)
4
+ require 'nokogiri'
5
+
6
+ require File.expand_path('../odf-report/images', __FILE__)
7
+ require File.expand_path('../odf-report/file_ops', __FILE__)
8
+ require File.expand_path('../odf-report/hash_gsub', __FILE__)
9
+ require File.expand_path('../odf-report/nested', __FILE__)
10
+ require File.expand_path('../odf-report/section', __FILE__)
11
+ require File.expand_path('../odf-report/table', __FILE__)
12
+ require File.expand_path('../odf-report/report', __FILE__)
@@ -2,6 +2,19 @@ module ODFReport
2
2
 
3
3
  module FileOps
4
4
 
5
+ def create_new_file(dest)
6
+
7
+ if dest
8
+ FileUtils.cp(@template, dest)
9
+ new_file = dest
10
+ else
11
+ FileUtils.cp(@template, @tmp_dir)
12
+ new_file = "#{@tmp_dir}/#{File.basename(@template)}"
13
+ end
14
+
15
+ return new_file
16
+ end
17
+
5
18
  def random_filename(opts={})
6
19
  opts = {:chars => ('0'..'9').to_a + ('A'..'F').to_a + ('a'..'f').to_a,
7
20
  :length => 24, :prefix => '', :suffix => '',
@@ -22,6 +22,12 @@ module ODFReport
22
22
  s.to_s.gsub("\n", "<text:line-break/>")
23
23
  end
24
24
 
25
+ def node_hash_gsub!(_node, hash_of_values)
26
+ txt = _node.inner_html
27
+ hash_gsub!(txt, hash_of_values)
28
+ _node.inner_html = txt
29
+ end
30
+
25
31
  end
26
32
 
27
33
  end
@@ -0,0 +1,37 @@
1
+ module ODFReport
2
+
3
+ module Images
4
+
5
+ def find_image_name_matches(content)
6
+
7
+ @images.each_pair do |image_name, path|
8
+ #Search for the image placeholder path
9
+ image_rgx = Regexp.new("draw:name=\"#{image_name}\".*?>.*<draw:image.*?xlink:href=\"([^\s]*)\" .*?\/>.*</draw:frame>", Regexp::MULTILINE)
10
+ content_match = content.match(image_rgx)
11
+
12
+ if content_match
13
+ placeholder_path = content_match[1]
14
+ @image_names_replacements[path] = File.basename(placeholder_path)
15
+ end
16
+ end
17
+
18
+ end
19
+
20
+ def replace_images(new_file)
21
+
22
+ unless @images.empty?
23
+ image_dir_name = "Pictures"
24
+ FileUtils.mkdir(File.join("#{@tmp_dir}", image_dir_name))
25
+ @image_names_replacements.each_pair do |path, template_image|
26
+ template_image_path = File.join(image_dir_name, template_image)
27
+ update_file_from_zip(new_file, template_image_path) do |content|
28
+ content.replace File.read(path)
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,42 @@
1
+ module ODFReport
2
+
3
+ module Nested
4
+
5
+ def replace_values!(new_section, data_item)
6
+ node_hash_gsub!(new_section, get_fields_with_values(data_item))
7
+ end
8
+
9
+ def get_fields_with_values(data_item)
10
+
11
+ fields_with_values = {}
12
+ @fields.each do |field_name, block1|
13
+ fields_with_values[field_name] = block1.call(data_item) || ''
14
+ end
15
+
16
+ fields_with_values
17
+ end
18
+
19
+ def get_collection_from_item(item, collection_field)
20
+
21
+ if collection_field.is_a?(Array)
22
+ tmp = item.dup
23
+ collection_field.each do |f|
24
+ if f.is_a?(Hash)
25
+ tmp = tmp.send(f.keys[0], f.values[0])
26
+ else
27
+ tmp = tmp.send(f)
28
+ end
29
+ end
30
+ collection = tmp
31
+ elsif collection_field.is_a?(Hash)
32
+ collection = item.send(collection_field.keys[0], collection_field.values[0])
33
+ else
34
+ collection = item.send(collection_field)
35
+ end
36
+
37
+ return collection
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -1,7 +1,7 @@
1
1
  module ODFReport
2
2
 
3
3
  class Report
4
- include HashGsub, FileOps
4
+ include HashGsub, FileOps, Images
5
5
 
6
6
  attr_accessor :values, :tables, :images, :sections
7
7
 
@@ -14,35 +14,31 @@ class Report
14
14
  @image_names_replacements = {}
15
15
  @sections = []
16
16
 
17
- @tmp_dir = Dir.tmpdir + "/" + random_filename(:prefix=>'odt_')
17
+ @tmp_dir = File.join(Dir.tmpdir, random_filename(:prefix=>'odt_'))
18
18
  Dir.mkdir(@tmp_dir) unless File.exists? @tmp_dir
19
19
 
20
20
  yield(self)
21
21
 
22
22
  end
23
23
 
24
- def add_section(section_name, collection, &block)
25
- sec = Section.new(section_name)
26
- @sections << sec
27
-
28
- yield(sec)
29
-
30
- sec.populate(collection)
31
-
32
- end
33
-
34
- def add_field(field_tag, value)
35
- @values[field_tag] = value || ''
24
+ def add_field(field_tag, value='')
25
+ @values[field_tag] = value
36
26
  end
37
27
 
38
28
  def add_table(table_name, collection, opts={}, &block)
39
- opts[:name] = table_name
29
+ opts.merge!(:name => table_name, :collection => collection)
40
30
  tab = Table.new(opts)
41
- yield(tab)
42
31
  @tables << tab
43
32
 
44
- tab.populate(collection)
33
+ yield(tab)
34
+ end
35
+
36
+ def add_section(section_name, collection, opts={}, &block)
37
+ opts.merge!(:name => section_name, :collection => collection)
38
+ sec = Section.new(opts)
39
+ @sections << sec
45
40
 
41
+ yield(sec)
46
42
  end
47
43
 
48
44
  def add_image(name, path)
@@ -51,41 +47,27 @@ class Report
51
47
 
52
48
  def generate(dest = nil)
53
49
 
54
- if dest
50
+ new_file = create_new_file(dest)
55
51
 
56
- FileUtils.cp(@template, dest)
57
- new_file = dest
52
+ %w(content.xml styles.xml).each do |content_file|
58
53
 
59
- else
54
+ update_file_from_zip(new_file, content_file) do |txt|
60
55
 
61
- FileUtils.cp(@template, @tmp_dir)
62
- new_file = "#{@tmp_dir}/#{File.basename(@template)}"
56
+ parse_document(txt) do |doc|
63
57
 
64
- end
58
+ replace_fields!(doc)
59
+ replace_sections!(doc)
60
+ replace_tables!(doc)
65
61
 
66
- %w(content.xml styles.xml).each do |content_file|
67
-
68
- update_file_from_zip(new_file, content_file) do |txt|
62
+ end
69
63
 
70
- replace_fields!(txt)
71
- replace_tables!(txt)
64
+ #TO_DO: make image use Nokogiri
72
65
  find_image_name_matches(txt)
73
- replace_sections!(txt)
74
-
75
66
  end
76
67
 
77
68
  end
78
69
 
79
- unless @images.empty?
80
- image_dir_name = "Pictures"
81
- FileUtils.mkdir(File.join("#{@tmp_dir}", image_dir_name))
82
- @image_names_replacements.each_pair do |path, template_image|
83
- template_image_path = File.join(image_dir_name, template_image)
84
- update_file_from_zip(new_file, template_image_path) do |content|
85
- content.replace File.read(path)
86
- end
87
- end
88
- end
70
+ replace_images(new_file)
89
71
 
90
72
  new_file
91
73
 
@@ -93,37 +75,28 @@ class Report
93
75
 
94
76
  private
95
77
 
78
+ def parse_document(txt)
79
+ doc = Nokogiri::XML(txt)
80
+ yield doc
81
+ txt.replace(doc.to_s)
82
+ end
83
+
96
84
  def replace_fields!(content)
97
- hash_gsub!(content, @values)
85
+ node_hash_gsub!(content, @values)
98
86
  end
99
87
 
100
88
  def replace_tables!(content)
101
-
102
89
  @tables.each do |table|
103
90
  table.replace!(content)
104
91
  end
105
-
106
92
  end
107
93
 
108
94
  def replace_sections!(content)
109
-
110
95
  @sections.each do |section|
111
96
  section.replace!(content)
112
97
  end
113
-
114
98
  end
115
99
 
116
- def find_image_name_matches(content)
117
- @images.each_pair do |image_name, path|
118
- #Search for the image placeholder path
119
- image_rgx = Regexp.new("draw:name=\"#{image_name}\".*?><draw:image.*?xlink:href=\"([^\s]*)\" .*?/></draw:frame>")
120
- content_match = content.match(image_rgx)
121
- if content_match
122
- placeholder_path = content_match[1]
123
- @image_names_replacements[path] = File.basename(placeholder_path)
124
- end
125
- end
126
- end
127
100
  end
128
101
 
129
102
  end
@@ -1,113 +1,93 @@
1
1
  module ODFReport
2
2
 
3
- class Section
4
- include HashGsub
3
+ class Section
4
+ include HashGsub, Nested
5
5
 
6
- attr_accessor :fields, :tables, :data, :name
6
+ attr_accessor :fields, :tables, :data, :name, :collection_field, :parent
7
7
 
8
- def initialize(name)
9
- @name = name
8
+ def initialize(opts)
9
+ @name = opts[:name]
10
+ @collection_field = opts[:collection_field]
11
+ @collection = opts[:collection]
12
+ @parent = opts[:parent]
10
13
 
11
- @fields = {}
12
- @data = []
13
- @tables = []
14
- end
14
+ @fields = {}
15
15
 
16
- def add_field(name, field=nil, &block)
17
- if field
18
- @fields[name] = lambda { |item| item.send(field)}
19
- else
20
- @fields[name] = block
16
+ @tables = []
17
+ @sections = []
21
18
  end
22
- end
23
-
24
- def add_table(table_name, collection_field, opts={}, &block)
25
- opts.merge!(:name => table_name, :collection_field => collection_field)
26
- tab = Table.new(opts)
27
- yield(tab)
28
- @tables << tab
29
-
30
- end
31
19
 
32
- def populate(collection)
33
-
34
- collection.each do |item|
35
- row = {}
36
- @fields.each do |field_name, block1|
37
- row[field_name] = block1.call(item)
20
+ def add_field(name, field=nil, &block)
21
+ if field
22
+ @fields[name] = lambda { |item| item.send(field)}
23
+ elsif block_given?
24
+ @fields[name] = block
25
+ else
26
+ @fields[name] = lambda { |item| item.send(name)}
38
27
  end
28
+ end
39
29
 
40
- row[:tables] = {}
41
- @tables.each do |table|
42
- collection = get_collection_from_item(item, table.collection_field)
43
- row[:tables][table.name] = table.values(collection)
44
- end
30
+ def add_table(table_name, collection_field, opts={}, &block)
31
+ opts.merge!(:name => table_name, :collection_field => collection_field, :parent => self)
32
+ tab = Table.new(opts)
33
+ @tables << tab
45
34
 
46
- @data << row
35
+ yield(tab)
47
36
  end
48
37
 
49
- end
38
+ def add_section(section_name, collection_field, opts={}, &block)
39
+ opts.merge!(:name => section_name, :collection_field => collection_field, :parent => self)
40
+ sec = Section.new(opts)
41
+ @sections << sec
50
42
 
51
- def replace!(content)
43
+ yield(sec)
44
+ end
52
45
 
53
- # search for the table inside the content
54
- section_rgx = Regexp.new("(<text:section.*?text:name=\"#{@name}.*?>(.*?)<\/text:section>)", "m")
55
- section_match = content.match(section_rgx)
46
+ def populate!(row)
47
+ @collection = get_collection_from_item(row, @collection_field) if row
48
+ end
56
49
 
57
- if section_match
58
- section_full = section_match[0]
59
- section_content = section_match[2]
50
+ def replace!(doc, row = nil)
60
51
 
61
- # extract the section from the content
62
- content.gsub!(section_full, "[SECTION_#{@name}]")
52
+ return unless section = find_section_node(doc)
63
53
 
64
- new_content = ""
54
+ template = section.dup
65
55
 
66
- # for each record
67
- @data.each do |_values|
56
+ populate!(row)
68
57
 
69
- # generates one new row (table-row), based in the model extracted
70
- # from the original table
71
- tmp_row = section_content.dup
58
+ @collection.each do |data_item|
59
+ new_section = template.dup
72
60
 
73
- # replace values in the section_content and stores in new_content
74
- hash_gsub!(tmp_row, _values)
61
+ replace_values!(new_section, data_item)
75
62
 
76
63
  @tables.each do |t|
77
- t.replace!(tmp_row, _values[:tables][t.name])
64
+ t.replace!(new_section, data_item)
65
+ end
66
+
67
+ @sections.each do |s|
68
+ s.replace!(new_section, data_item)
78
69
  end
79
70
 
80
- new_content << tmp_row
71
+ section.before(new_section)
72
+
81
73
  end
82
74
 
83
- # replace back the table into content
84
- content.gsub!("[SECTION_#{@name}]", new_content)
75
+ section.remove
85
76
 
86
- end # if table match
77
+ end # replace_section
87
78
 
88
- end # replace_section
79
+ private
89
80
 
90
- private
81
+ def find_section_node(doc)
91
82
 
92
- def get_collection_from_item(item, collection_field)
83
+ prefix = @parent ? "" : "//"
84
+
85
+ sections = doc.xpath("#{prefix}text:section[@text:name='#{@name}']")
86
+
87
+ sections.empty? ? nil : sections.first
93
88
 
94
- if collection_field.is_a?(Array)
95
- tmp = item.dup
96
- collection_field.each do |f|
97
- if f.is_a?(Hash)
98
- tmp = tmp.send(f.keys[0], f.values[0])
99
- else
100
- tmp = tmp.send(f)
101
- end
102
- end
103
- collection = tmp
104
- else
105
- collection = item.send(collection_field)
106
89
  end
107
90
 
108
- return collection
109
91
  end
110
92
 
111
- end
112
-
113
93
  end
@@ -1,19 +1,20 @@
1
1
  module ODFReport
2
2
 
3
3
  class Table
4
- include HashGsub
4
+ include HashGsub, Nested
5
5
 
6
- attr_accessor :fields, :rows, :name, :collection_field, :data, :header
6
+ attr_accessor :fields, :rows, :name, :collection_field, :data, :header, :parent
7
7
 
8
8
  def initialize(opts)
9
9
  @name = opts[:name]
10
10
  @collection_field = opts[:collection_field]
11
11
  @collection = opts[:collection]
12
- @header = opts[:header] || false
12
+ @parent = opts[:parent]
13
13
 
14
14
  @fields = {}
15
- @rows = []
16
- @data = []
15
+
16
+ @template_rows = []
17
+ @header = opts[:header] || false
17
18
  end
18
19
 
19
20
  def add_column(name, field=nil, &block)
@@ -26,104 +27,68 @@ class Table
26
27
  end
27
28
  end
28
29
 
29
- def values(collection)
30
- ret = []
31
- collection.each do |item|
32
- row = {}
33
- @fields.each do |field_name, block1|
34
- row[field_name] = block1.call(item) || ''
35
- end
36
- ret << row
37
- end
38
- ret
39
- end
40
-
41
- def populate(collection)
42
- @data = values(collection)
30
+ def populate!(row)
31
+ @collection = get_collection_from_item(row, @collection_field) if row
43
32
  end
44
33
 
45
- def replace!(content, rows = nil)
46
- @data = rows if rows
47
-
48
- # search for the table inside the content
49
- table_rgx = Regexp.new("(<table:table table:name=\"#{@name}.*?>.*?<\/table:table>)", "m")
50
- table_match = content.match(table_rgx)
51
-
52
- if table_match
53
- table = table_match[0]
34
+ def replace!(doc, row = nil)
54
35
 
55
- # extract the table from the content
56
- content.gsub!(table, "[TABLE_#{@name}]")
36
+ return unless table = find_table_node(doc)
57
37
 
58
- # search for the table:row's
59
- row_rgx = Regexp.new("(<table:table-row.*?<\/table:table-row>)", "m")
38
+ populate!(row)
60
39
 
61
- # use scan (instead of match) as the table can have more than one table-row (header and data)
62
- # and scan returns all matches
63
- row_match = table.scan(row_rgx)
40
+ @template_rows = table.xpath("table:table-row")
64
41
 
65
- unless row_match.empty?
42
+ @collection.each do |data_item|
66
43
 
67
- replace_rows!(table, row_match)
44
+ new_node = get_next_row
68
45
 
69
- new_rows = ""
46
+ replace_values!(new_node, data_item)
70
47
 
71
- # for each record
72
- @data.each do |_values|
48
+ table.add_child(new_node)
73
49
 
74
- # generates one new row (table-row), based in the model extracted
75
- # from the original table
76
- tmp_row = get_next_row.dup
77
-
78
- # replace values in the model_row and stores in new_rows
79
- hash_gsub!(tmp_row, _values)
80
-
81
- new_rows << tmp_row
82
- end
50
+ end
83
51
 
84
- # replace back the lines into the table
85
- table.gsub!("[ROW_#{@name}]", new_rows)
52
+ @template_rows.each_with_index do |r, i|
53
+ r.remove if (get_start_node..template_lenght) === i
54
+ end
86
55
 
87
- end # unless row_match.empty?
56
+ end # replace
88
57
 
89
- # replace back the table into content
90
- if @data.empty?
91
- content.gsub!("[TABLE_#{@name}]", "")
92
- else
93
- content.gsub!("[TABLE_#{@name}]", table)
94
- end
58
+ private
95
59
 
96
- end # if table match
60
+ def get_next_row
61
+ @row_cursor = get_start_node unless defined?(@row_cursor)
97
62
 
98
- end # replace
63
+ ret = @template_rows[@row_cursor]
64
+ if @template_rows.size == @row_cursor + 1
65
+ @row_cursor = get_start_node
66
+ else
67
+ @row_cursor += 1
68
+ end
69
+ return ret.dup
70
+ end
99
71
 
100
- private
72
+ def get_start_node
73
+ @header ? 1 : 0
74
+ end
101
75
 
102
- def replace_rows!(table, rows)
76
+ def reset
77
+ @row_cursor = get_start_node
78
+ end
103
79
 
104
- rows.delete_at(0) if @header # ignore the header
80
+ def template_lenght
81
+ @tl ||= @template_rows.size
82
+ end
105
83
 
106
- @rows = rows.dup
107
- @row_cursor = 0
84
+ def find_table_node(doc)
108
85
 
109
- # extract the rows from the table
110
- first = rows.delete_at(0)[0]
111
- table.gsub!(first, "[ROW_#{@name}]")
86
+ prefix = @parent ? "" : "//"
112
87
 
113
- rows.each do |r|
114
- table.gsub!(r[0], "")
115
- end
88
+ tables = doc.xpath("#{prefix}table:table[@table:name='#{@name}']")
116
89
 
117
- end
90
+ tables.empty? ? nil : tables.first
118
91
 
119
- def get_next_row
120
- ret = @rows[@row_cursor]
121
- if @rows.size == @row_cursor + 1
122
- @row_cursor = 0
123
- else
124
- @row_cursor += 1
125
- end
126
- return ret[0]
127
92
  end
128
93
 
129
94
  end
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{odf-report}
5
- s.version = "0.3.3"
5
+ s.version = "0.4.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Sandro Duarte"]
9
- s.date = %q{2011-01-24}
9
+ s.date = %q{2011-09-23}
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
12
  s.extra_rdoc_files = ["lib/odf-report.rb", "README.textile"]
13
- s.files = %w{lib/odf-report.rb odf-report.gemspec README.textile test/test.odt test/test.rb Manifest lib/odf-report/report.rb lib/odf-report/table.rb lib/odf-report/section.rb lib/odf-report/file_ops.rb lib/odf-report/hash_gsub.rb }
13
+ s.files = %w{lib/odf-report.rb odf-report.gemspec README.textile Manifest lib/odf-report/report.rb lib/odf-report/table.rb lib/odf-report/section.rb lib/odf-report/file_ops.rb lib/odf-report/hash_gsub.rb lib/odf-report/images.rb lib/odf-report/nested.rb }
14
14
  s.has_rdoc = false
15
15
  s.homepage = %q{}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Odf-report", "--main", "README.textile"]
@@ -24,10 +24,13 @@ Gem::Specification.new do |s|
24
24
 
25
25
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
26
  s.add_runtime_dependency(%q<rubyzip>, [">= 0", ">= 0.9.4"])
27
+ s.add_runtime_dependency(%q<nokogiri>, [">= 0", ">= 1.5.0"])
27
28
  else
28
29
  s.add_dependency(%q<rubyzip>, [">= 0", ">= 0.9.4"])
30
+ s.add_dependency(%q<nokogiri>, [">= 0", ">= 1.5.0"])
29
31
  end
30
32
  else
31
33
  s.add_dependency(%q<rubyzip>, [">= 0", ">= 0.9.4"])
34
+ s.add_dependency(%q<nokogiri>, [">= 0", ">= 1.5.0"])
32
35
  end
33
36
  end
metadata CHANGED
@@ -1,97 +1,91 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: odf-report
3
- version: !ruby/object:Gem::Version
4
- prerelease: false
5
- segments:
6
- - 0
7
- - 3
8
- - 3
9
- version: 0.3.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
10
6
  platform: ruby
11
- authors:
7
+ authors:
12
8
  - Sandro Duarte
13
9
  autorequire:
14
10
  bindir: bin
15
11
  cert_chain: []
16
-
17
- date: 2011-01-24 00:00:00 -02:00
18
- default_executable:
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
12
+ date: 2011-09-23 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
21
15
  name: rubyzip
22
- prerelease: false
23
- requirement: &id001 !ruby/object:Gem::Requirement
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- segments:
28
- - 0
29
- version: "0"
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- segments:
33
- - 0
34
- - 9
35
- - 4
16
+ requirement: &2152736240 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
36
24
  version: 0.9.4
37
25
  type: :runtime
38
- version_requirements: *id001
26
+ prerelease: false
27
+ version_requirements: *2152736240
28
+ - !ruby/object:Gem::Dependency
29
+ name: nokogiri
30
+ requirement: &2152735160 !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: 1.5.0
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: *2152735160
39
42
  description: Generates ODF files, given a template (.odt) and data, replacing tags
40
43
  email: sandrods@gmail.com
41
44
  executables: []
42
-
43
45
  extensions: []
44
-
45
- extra_rdoc_files:
46
+ extra_rdoc_files:
46
47
  - lib/odf-report.rb
47
48
  - README.textile
48
- files:
49
+ files:
49
50
  - lib/odf-report.rb
50
51
  - odf-report.gemspec
51
52
  - README.textile
52
- - test/test.odt
53
- - test/test.rb
54
53
  - Manifest
55
54
  - lib/odf-report/report.rb
56
55
  - lib/odf-report/table.rb
57
56
  - lib/odf-report/section.rb
58
57
  - lib/odf-report/file_ops.rb
59
58
  - lib/odf-report/hash_gsub.rb
60
- has_rdoc: true
61
- homepage: ""
59
+ - lib/odf-report/images.rb
60
+ - lib/odf-report/nested.rb
61
+ homepage: ''
62
62
  licenses: []
63
-
64
63
  post_install_message:
65
- rdoc_options:
64
+ rdoc_options:
66
65
  - --line-numbers
67
66
  - --inline-source
68
67
  - --title
69
68
  - Odf-report
70
69
  - --main
71
70
  - README.textile
72
- require_paths:
71
+ require_paths:
73
72
  - lib
74
- required_ruby_version: !ruby/object:Gem::Requirement
75
- requirements:
76
- - - ">="
77
- - !ruby/object:Gem::Version
78
- segments:
79
- - 0
80
- version: "0"
81
- required_rubygems_version: !ruby/object:Gem::Requirement
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- segments:
86
- - 1
87
- - 2
88
- version: "1.2"
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '1.2'
89
85
  requirements: []
90
-
91
86
  rubyforge_project:
92
- rubygems_version: 1.3.6
87
+ rubygems_version: 1.8.10
93
88
  signing_key:
94
89
  specification_version: 2
95
90
  summary: Generates ODF files, given a template (.odt) and data, replacing tags
96
91
  test_files: []
97
-
Binary file
@@ -1,78 +0,0 @@
1
- require '../lib/odf-report'
2
- require 'ostruct'
3
-
4
- col1 = []
5
- (1..15).each do |i|
6
- col1 << OpenStruct.new({:name=>"name #{i}", :id=>i, :address=>"this is address #{i}"})
7
- end
8
-
9
-
10
- col2 = []
11
- col2 << OpenStruct.new({:name=>"josh harnet", :id=>"02", :address=>"testing <&> ", :phone=>99025668, :zip=>"90420-002"})
12
- col2 << OpenStruct.new({:name=>"sandro duarte", :id=>"45", :address=>"address with &", :phone=>88774451, :zip=>"90490-002"})
13
- col2 << OpenStruct.new({:name=>"ellen bicca", :id=>"77", :address=>"<address with escaped html>", :phone=>77025668, :zip=>"94420-002"})
14
- col2 << OpenStruct.new({:name=>"luiz garcia", :id=>"88", :address=>"address with\nlinebreak", :phone=>27025668, :zip=>"94520-025"})
15
-
16
- report = ODFReport::Report.new("test.odt") do |r|
17
-
18
- r.add_field("HEADER_FIELD", "This field was in the HEADER")
19
-
20
- r.add_field("TAG_01", "New tag")
21
- r.add_field("TAG_02", "TAG-2 -> New tag")
22
-
23
- r.add_table("TABLE_01", col1, :header=>true) do |t|
24
- t.add_column(:field_01, :id)
25
- t.add_column(:field_02, :name)
26
- t.add_column(:field_03, :address)
27
- end
28
-
29
- r.add_table("TABLE_02", col2) do |t|
30
- t.add_column(:field_04, :id)
31
- t.add_column(:field_05, :name)
32
- t.add_column(:field_06, :address)
33
- t.add_column(:field_07, :phone)
34
- t.add_column(:field_08, :zip)
35
- end
36
-
37
- r.add_image("graphics1", File.join(Dir.pwd, 'piriapolis.jpg'))
38
-
39
- end
40
-
41
- report.generate("result.odt")
42
-
43
- class Item
44
- attr_accessor :name, :sid, :children
45
- def initialize(_name, _sid, _children=[])
46
- @name=_name
47
- @sid=_sid
48
- @children=_children
49
- end
50
- end
51
-
52
- items = []
53
- items << Item.new("Dexter Morgan", '007', %w(sawyer juliet hurley locke jack freckles))
54
- items << Item.new("Danny Crane", '302', %w(sidney sloane jack michael marshal))
55
- items << Item.new("Coach Taylor", '220', %w(meredith christina izzie alex george))
56
-
57
- report = ODFReport::Report.new("sections.odt") do |r|
58
-
59
- r.add_field("TAG_01", "New tag")
60
- r.add_field("TAG_02", "TAG-2 -> New tag")
61
-
62
- r.add_section("SECTION_01", items) do |s|
63
-
64
- s.add_field('NAME') do |i|
65
- i.name
66
- end
67
-
68
- s.add_field('SID', :sid)
69
-
70
- s.add_table('TABLE_S1', :children, :header=>true) do |t|
71
- t.add_column('NAME1') { |item| "-> #{item}" }
72
- t.add_column('INV') { |item| item.to_s.reverse.upcase }
73
- end
74
- end
75
-
76
- end
77
-
78
- report.generate("section_result.odt")