flexy-odf-report 0.1.6 → 0.4.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.
data/README.textile CHANGED
@@ -1,13 +1,22 @@
1
1
  h1. ODF-REPORT
2
2
 
3
3
  Gem for generating .odt files by making strings, images, tables and sections replacements in a previously created .odt file.
4
+ This fork matches Sandro's version 0.4.1 but adds support for automatic omitting of empty table rows.
4
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>
5
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/>
data/lib/odf-report.rb CHANGED
@@ -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,33 @@
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
+ if node = content.xpath("//draw:frame[@draw:name='#{image_name}']/draw:image").first
9
+ placeholder_path = node.attribute('href').value
10
+ @image_names_replacements[path] = File.basename(placeholder_path)
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ def replace_images(new_file)
17
+
18
+ unless @images.empty?
19
+ image_dir_name = "Pictures"
20
+ FileUtils.mkdir(File.join("#{@tmp_dir}", image_dir_name))
21
+ @image_names_replacements.each_pair do |path, template_image|
22
+ template_image_path = File.join(image_dir_name, template_image)
23
+ update_file_from_zip(new_file, template_image_path) do |content|
24
+ content.replace File.read(path)
25
+ end
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -0,0 +1,55 @@
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
+ force_fill_with_empty_string = false
12
+
13
+ fields_with_values = {}
14
+ 2.times.each do
15
+ @fields.each do |field_name, block1|
16
+ cell = block1.call(data_item) || ''
17
+ fields_with_values[field_name] = cell unless !force_fill_with_empty_string && (cell.nil? || cell.strip.blank?) && @skip_empty_rows
18
+ end
19
+ if row.empty?
20
+ break
21
+ else
22
+ # If - finally - the row is *not* empty all template variables in
23
+ # all empty cells must be replaced by the empty string. Otherwise
24
+ # the template variable is rendered ("[some-template-var]")...
25
+ force_fill_with_empty_string = true
26
+ end
27
+ end
28
+
29
+ fields_with_values
30
+ end
31
+
32
+ def get_collection_from_item(item, collection_field)
33
+
34
+ if collection_field.is_a?(Array)
35
+ tmp = item.dup
36
+ collection_field.each do |f|
37
+ if f.is_a?(Hash)
38
+ tmp = tmp.send(f.keys[0], f.values[0])
39
+ else
40
+ tmp = tmp.send(f)
41
+ end
42
+ end
43
+ collection = tmp
44
+ elsif collection_field.is_a?(Hash)
45
+ collection = item.send(collection_field.keys[0], collection_field.values[0])
46
+ else
47
+ collection = item.send(collection_field)
48
+ end
49
+
50
+ return collection
51
+ end
52
+
53
+ end
54
+
55
+ 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,79 +47,56 @@ class Report
51
47
 
52
48
  def generate(dest = nil)
53
49
 
54
- if dest
55
-
56
- FileUtils.cp(@template, dest)
57
- new_file = dest
58
-
59
- else
60
-
61
- FileUtils.cp(@template, @tmp_dir)
62
- new_file = "#{@tmp_dir}/#{File.basename(@template)}"
63
-
64
- end
50
+ new_file = create_new_file(dest)
65
51
 
66
52
  %w(content.xml styles.xml).each do |content_file|
67
53
 
68
54
  update_file_from_zip(new_file, content_file) do |txt|
69
55
 
70
- replace_fields!(txt)
71
- replace_tables!(txt)
72
- find_image_name_matches(txt)
73
- replace_sections!(txt)
56
+ parse_document(txt) do |doc|
74
57
 
75
- end
58
+ replace_fields!(doc)
59
+ replace_sections!(doc)
60
+ replace_tables!(doc)
76
61
 
77
- end
62
+ find_image_name_matches(doc)
78
63
 
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
64
  end
65
+
87
66
  end
67
+
88
68
  end
89
69
 
70
+ replace_images(new_file)
71
+
90
72
  new_file
91
73
 
92
74
  end
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,147 +1,96 @@
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
13
-
14
- @skip_empty_rows = opts[:skip_empty_rows] || false
12
+ @parent = opts[:parent]
15
13
 
16
14
  @fields = {}
17
- @rows = []
18
- @data = []
15
+
16
+ @template_rows = []
17
+ @header = opts[:header] || false
19
18
  end
20
19
 
21
20
  def add_column(name, field=nil, &block)
22
21
  if field
23
- @fields[name] = lambda { |item| item.send(field) }
22
+ @fields[name] = lambda { |item| item.send(field)}
24
23
  elsif block_given?
25
24
  @fields[name] = block
26
25
  else
27
- @fields[name] = lambda { |item| item.send(name) }
26
+ @fields[name] = lambda { |item| item.send(name)}
28
27
  end
29
28
  end
30
29
 
31
- def values(collection)
32
- ret = []
33
- collection.each do |item|
34
- row = {}
35
-
36
- force_fill_with_empty_string = false
37
- 2.times.each do
38
- @fields.each do |field_name, block1|
39
- cell = block1.call(item) || ''
40
- row[field_name] = cell unless !force_fill_with_empty_string && (cell.nil? || cell.strip.blank?) && @skip_empty_rows
41
- end
42
- if row.empty?
43
- break
44
- else
45
- # If - finally - the row is *not* empty all template variables in
46
- # all empty cells must be replaced by the empty string. Otherwise
47
- # the template variable is rendered ("[some-template-var]")...
48
- force_fill_with_empty_string = true
49
- end
50
- end
51
-
52
- ret << row unless row.empty? && @skip_empty_rows
53
- end
54
- ret
55
- end
56
-
57
- def populate(collection)
58
- @data = values(collection)
30
+ def populate!(row)
31
+ @collection = get_collection_from_item(row, @collection_field) if row
59
32
  end
60
33
 
61
- def replace!(content, rows = nil)
62
- @data = rows if rows
63
-
64
- # search for the table inside the content
65
- table_rgx = Regexp.new("(<table:table table:name=\"#{@name}.*?>.*?<\/table:table>)", "m")
66
- table_match = content.match(table_rgx)
34
+ def replace!(doc, row = nil)
67
35
 
68
- if table_match
69
- table = table_match[0]
36
+ return unless table = find_table_node(doc)
70
37
 
71
- # extract the table from the content
72
- content.gsub!(table, "[TABLE_#{@name}]")
38
+ populate!(row)
73
39
 
74
- # search for the table:row's
75
- row_rgx = Regexp.new("(<table:table-row.*?<\/table:table-row>)", "m")
40
+ @template_rows = table.xpath("table:table-row")
76
41
 
77
- # use scan (instead of match) as the table can have more than one table-row (header and data)
78
- # and scan returns all matches
79
- row_match = table.scan(row_rgx)
42
+ @collection.each do |data_item|
80
43
 
81
- unless row_match.empty?
44
+ new_node = get_next_row
82
45
 
83
- replace_rows!(table, row_match)
46
+ replace_values!(new_node, data_item)
84
47
 
85
- new_rows = ""
48
+ table.add_child(new_node)
86
49
 
87
- # for each record
88
- @data.each do |_values|
89
-
90
- # generates one new row (table-row), based in the model extracted
91
- # from the original table
92
- tmp_row = get_next_row.dup
93
-
94
- # replace values in the model_row and stores in new_rows
95
- hash_gsub!(tmp_row, _values)
96
-
97
- new_rows << tmp_row
98
- end
50
+ end
99
51
 
100
- # replace back the lines into the table
101
- table.gsub!("[ROW_#{@name}]", new_rows)
52
+ @template_rows.each_with_index do |r, i|
53
+ r.remove if (get_start_node..template_length) === i
54
+ end
102
55
 
103
- end # unless row_match.empty?
56
+ end # replace
104
57
 
105
- # replace back the table into content
106
- if @data.empty?
107
- content.gsub!("[TABLE_#{@name}]", "")
108
- else
109
- content.gsub!("[TABLE_#{@name}]", table)
110
- end
58
+ private
111
59
 
112
- end # if table match
60
+ def get_next_row
61
+ @row_cursor = get_start_node unless defined?(@row_cursor)
113
62
 
114
- 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
115
71
 
116
- private
72
+ def get_start_node
73
+ @header ? 1 : 0
74
+ end
117
75
 
118
- def replace_rows!(table, rows)
76
+ def reset
77
+ @row_cursor = get_start_node
78
+ end
119
79
 
120
- rows.delete_at(0) if @header # ignore the header
80
+ def template_length
81
+ @tl ||= @template_rows.size
82
+ end
121
83
 
122
- @rows = rows.dup
123
- @row_cursor = 0
84
+ def find_table_node(doc)
124
85
 
125
- # extract the rows from the table
126
- first = rows.delete_at(0)[0]
127
- table.gsub!(first, "[ROW_#{@name}]")
86
+ prefix = @parent ? "" : "//"
128
87
 
129
- rows.each do |r|
130
- table.gsub!(r[0], "")
131
- end
88
+ tables = doc.xpath("#{prefix}table:table[@table:name='#{@name}']")
132
89
 
133
- end
90
+ tables.empty? ? nil : tables.first
134
91
 
135
- def get_next_row
136
- ret = @rows[@row_cursor]
137
- if @rows.size == @row_cursor + 1
138
- @row_cursor = 0
139
- else
140
- @row_cursor += 1
141
- end
142
- return ret[0]
143
92
  end
144
93
 
145
94
  end
146
95
 
147
- end
96
+ end
data/odf-report.gemspec CHANGED
@@ -2,21 +2,21 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{flexy-odf-report}
5
- s.version = "0.1.6"
5
+ s.version = "0.4.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Sandro Duarte", "Mark von Zeschau"]
9
- s.date = %q{2011-06-07}
10
- s.description = %q{Generates ODF files, given a template (.odt) and data, replacing tags. Same as the original odf-report gem but adds some more features.}
8
+ s.authors = ["Sandro Duarte"]
9
+ s.date = %q{2011-10-04}
10
+ s.description = %q{Generates ODF files, given a template (.odt) and data, replacing tags. Matches Sandro's version 0.4.1 but adds support for automatic omitting of empty table rows. }
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"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubygems_version = %q{1.3.7}
19
- s.summary = %q{Generates ODF files, given a template (.odt) and data, replacing tags. Same as the original odf-report gem but adds some more features.}
19
+ s.summary = %q{Generates ODF files, given a template (.odt) and data, replacing tags}
20
20
 
21
21
  if s.respond_to? :specification_version then
22
22
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -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,86 +1,93 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: flexy-odf-report
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.2
4
5
  prerelease:
5
- version: 0.1.6
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Sandro Duarte
9
- - Mark von Zeschau
10
9
  autorequire:
11
10
  bindir: bin
12
11
  cert_chain: []
13
-
14
- date: 2011-06-07 00:00:00 +02:00
15
- default_executable:
16
- dependencies:
17
- - !ruby/object:Gem::Dependency
12
+ date: 2011-10-04 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
18
15
  name: rubyzip
19
- prerelease: false
20
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &70232150011140 !ruby/object:Gem::Requirement
21
17
  none: false
22
- requirements:
23
- - - ">="
24
- - !ruby/object:Gem::Version
25
- version: "0"
26
- - - ">="
27
- - !ruby/object:Gem::Version
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ - - ! '>='
23
+ - !ruby/object:Gem::Version
28
24
  version: 0.9.4
29
25
  type: :runtime
30
- version_requirements: *id001
31
- description: Generates ODF files, given a template (.odt) and data, replacing tags. Same as the original odf-report gem but adds some more features.
26
+ prerelease: false
27
+ version_requirements: *70232150011140
28
+ - !ruby/object:Gem::Dependency
29
+ name: nokogiri
30
+ requirement: &70232150010300 !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: *70232150010300
42
+ description: ! 'Generates ODF files, given a template (.odt) and data, replacing tags.
43
+ Matches Sandro''s version 0.4.1 but adds support for automatic omitting of empty
44
+ table rows. '
32
45
  email: sandrods@gmail.com
33
46
  executables: []
34
-
35
47
  extensions: []
36
-
37
- extra_rdoc_files:
48
+ extra_rdoc_files:
38
49
  - lib/odf-report.rb
39
50
  - README.textile
40
- files:
51
+ files:
41
52
  - lib/odf-report.rb
42
53
  - odf-report.gemspec
43
54
  - README.textile
44
- - test/test.odt
45
- - test/test.rb
46
55
  - Manifest
47
56
  - lib/odf-report/report.rb
48
57
  - lib/odf-report/table.rb
49
58
  - lib/odf-report/section.rb
50
59
  - lib/odf-report/file_ops.rb
51
60
  - lib/odf-report/hash_gsub.rb
52
- has_rdoc: true
53
- homepage: ""
61
+ - lib/odf-report/images.rb
62
+ - lib/odf-report/nested.rb
63
+ homepage: ''
54
64
  licenses: []
55
-
56
65
  post_install_message:
57
- rdoc_options:
66
+ rdoc_options:
58
67
  - --line-numbers
59
68
  - --inline-source
60
69
  - --title
61
70
  - Odf-report
62
71
  - --main
63
72
  - README.textile
64
- require_paths:
73
+ require_paths:
65
74
  - lib
66
- required_ruby_version: !ruby/object:Gem::Requirement
75
+ required_ruby_version: !ruby/object:Gem::Requirement
67
76
  none: false
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- version: "0"
72
- required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
82
  none: false
74
- requirements:
75
- - - ">="
76
- - !ruby/object:Gem::Version
77
- version: "1.2"
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '1.2'
78
87
  requirements: []
79
-
80
88
  rubyforge_project:
81
- rubygems_version: 1.5.2
89
+ rubygems_version: 1.8.11
82
90
  signing_key:
83
91
  specification_version: 2
84
- summary: Generates ODF files, given a template (.odt) and data, replacing tags. Same as the original odf-report gem but adds some more features.
92
+ summary: Generates ODF files, given a template (.odt) and data, replacing tags
85
93
  test_files: []
86
-
data/test/test.odt DELETED
Binary file
data/test/test.rb DELETED
@@ -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")