serenity-odt 0.1.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.
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2010 Tomas Kramar
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
@@ -0,0 +1,60 @@
1
+ Serenity is an embedded ruby for OpenOffice documents (.odt files). You provide an .odt template with ruby code inside a special markup and the data and Serenity generates the document. If you know erb all of this should sound familiar.
2
+
3
+ Serenity is best demonstrated with a picture. The first picture shows the template with the ruby code, next image shows the generated document. The template, output and the sample script can be found in the showcase directory.
4
+
5
+ ![Serenity template](http://github.com/kremso/serenity/blob/master/showcase/imgs/serenity_template.png?raw=true)
6
+
7
+ ![Generated document](http://github.com/kremso/serenity/blob/master/showcase/imgs/serenity_output.png?raw=true)
8
+
9
+ Installation
10
+ ============
11
+
12
+ gem install serenity-odt
13
+
14
+ Yeah, serenity is already taken on gemcutter.
15
+
16
+ Creating templates
17
+ ===================
18
+
19
+ Templates are created directly in OpenOffice. Ruby code is enclosed in special markup:
20
+ * `{%= %}` is for ruby code which should be output to the final document. `to_s` is applied to anything found inside this markup
21
+ * `{% %}` is for everything else — loops, ifs, ends and any other non-outputting code
22
+
23
+ Any special formatting should by applied directly on the markup. E.g. if you need to ouput the value of variable title in bold font, write `{%= title %}`, select in in OpenOffice and make it bold. See the showcase.odt for more examples.
24
+
25
+ Generating documents
26
+ ====================
27
+
28
+ require 'rubygems'
29
+ require 'serenity'
30
+
31
+ class Showcase
32
+ include Serenity::Generator
33
+
34
+ Person = Struct.new(:name, :items)
35
+ Item = Struct.new(:name, :usage)
36
+
37
+ def generate_showcase
38
+ @title = 'Serenity inventory'
39
+
40
+ mals_items = [Item.new('Moses Brothers Self-Defense Engine Frontier Model B', 'Lock and load')]
41
+ mal = Person.new('Malcolm Reynolds', mals_items)
42
+
43
+ jaynes_items = [Item.new('Vera', 'Callahan full-bore auto-lock with a customized trigger, double cartridge and thorough gauge'),
44
+ Item.new('Lux', 'Ratatata'),
45
+ Item.new('Knife', 'Cut-throat')]
46
+ jayne = Person.new('Jayne Cobb', jaynes_items)
47
+
48
+ @crew = [mal, jayne]
49
+
50
+ render_odt 'showcase.odt'
51
+ end
52
+ end
53
+
54
+ The key parts are `include Serenity::Generator` and render_odt. The data for the template must be provided as instance variables.
55
+
56
+ Contact
57
+ =======
58
+
59
+ kramar[dot]tomas[at]gmail.com — I love the attention
60
+
@@ -0,0 +1,36 @@
1
+ require 'rake'
2
+ require 'spec/rake/spectask'
3
+
4
+ task :default => [:spec]
5
+
6
+ Spec::Rake::SpecTask.new("spec")
7
+
8
+ spec = Gem::Specification.new do |s|
9
+ s.name = %q{serenity-odt}
10
+ s.version = "0.1.0"
11
+
12
+ s.authors = ["Tomas Kramar"]
13
+ s.description = <<-EOF
14
+ Embedded ruby for OpenOffice Text Document (.odt) files. You provide an .odt template
15
+ with ruby code in a special markup and the data, and Serenity generates the document.
16
+ Very similar to .erb files.
17
+ EOF
18
+ s.email = %q{kramar.tomas@gmail.com}
19
+ s.files = Dir.glob('lib/**/*.rb') + %w{README.md Rakefile serenity-odt.gemspec LICENSE}
20
+ s.has_rdoc = false
21
+ s.require_paths = ["lib"]
22
+ s.rubygems_version = %q{1.3.5}
23
+ s.summary = %q{Embedded ruby for OpenOffice Text Document (.odt) files}
24
+ s.test_files = Dir.glob('spec/**/*.rb') + Dir.glob('fixtures/*.odt')
25
+ s.add_dependency('rubyzip', '>= 0.9.1')
26
+ s.add_development_dependency('rspec', '>= 1.2.9')
27
+ end
28
+
29
+ task :gemspec do
30
+ File.open("serenity-odt.gemspec", "w") { |f| f << spec.to_ruby }
31
+ end
32
+
33
+ task :gem => :gemspec do
34
+ system "gem build serenity-odt.gemspec"
35
+ end
36
+
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'serenity/line'
3
+ require 'serenity/debug'
4
+ require 'serenity/node_type'
5
+ require 'serenity/odteruby'
6
+ require 'serenity/template'
7
+ require 'serenity/xml_reader'
8
+ require 'serenity/generator'
@@ -0,0 +1,19 @@
1
+ module Serenity
2
+ module Debug
3
+ def debug?
4
+ false
5
+ end
6
+
7
+ def debug_file_path
8
+ File.join(debug_dir, debug_file_name)
9
+ end
10
+
11
+ def debug_file_name
12
+ "serenity_debug_#{rand(100)}.rb"
13
+ end
14
+
15
+ def debug_dir
16
+ File.join(File.dirname(__FILE__), '..', '..', 'debug')
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,31 @@
1
+ require 'ruby-debug'
2
+
3
+ module Serenity
4
+ module Generator
5
+ def render_odt template_path, output_path = output_name(template_path)
6
+
7
+ local_variables = {}
8
+ instance_variables.each { |name| local_variables[name] = instance_variable_get(name) }
9
+
10
+ locals = instance_variables.map { |name| "#{ival_name_to_local(name)} = local_variables['#{name}'];" }.join
11
+ eval locals
12
+
13
+ template = Template.new template_path, output_path
14
+ template.process binding
15
+ end
16
+
17
+ private
18
+
19
+ def ival_name_to_local ival_name
20
+ ival_name[1, ival_name.length]
21
+ end
22
+
23
+ def output_name input
24
+ if input =~ /(.+)\.odt\Z/
25
+ "#{$1}_output.odt"
26
+ else
27
+ "#{input}_output.odt"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,56 @@
1
+ module Serenity
2
+ class Line
3
+ attr_reader :text
4
+
5
+ def initialize text
6
+ @text = text
7
+ end
8
+
9
+ def to_s
10
+ @text
11
+ end
12
+
13
+ def self.text txt
14
+ TextLine.new txt
15
+ end
16
+
17
+ def self.code txt
18
+ CodeLine.new txt
19
+ end
20
+
21
+ def self.string txt
22
+ StringLine.new txt
23
+ end
24
+
25
+ end
26
+
27
+ class TextLine < Line
28
+ def to_buf
29
+ " _buf << '" << escape_text(@text) << "';"
30
+ end
31
+
32
+ def escape_text text
33
+ text.gsub(/['\\]/, '\\\\\&')
34
+ end
35
+ end
36
+
37
+ class CodeLine < Line
38
+ def to_buf
39
+ escape_code(@text) << ';'
40
+ end
41
+
42
+ def escape_code code
43
+ code.gsub!('&apos;', "'")
44
+ code.gsub!('&gt;', ">")
45
+ code.gsub!('&lt;', "<")
46
+ code
47
+ end
48
+ end
49
+
50
+ class StringLine < CodeLine
51
+ def to_buf
52
+ " _buf << (" << escape_code(@text) << ").to_s;"
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,7 @@
1
+ module Serenity
2
+ class NodeType
3
+ TAG = 1
4
+ CONTROL = 2
5
+ TEMPLATE = 3
6
+ end
7
+ end
@@ -0,0 +1,88 @@
1
+ module Serenity
2
+ class OdtEruby
3
+ include Debug
4
+
5
+ EMBEDDED_PATTERN = /\{%(=+)?(.*?)-?%\}/m
6
+
7
+ def initialize template
8
+ @src = convert template
9
+ if debug?
10
+ File.open(debug_file_path, 'w') do |f|
11
+ f << @src
12
+ end
13
+ end
14
+ end
15
+
16
+ def evaluate context
17
+ eval(@src, context)
18
+ end
19
+
20
+ private
21
+
22
+ def convert template
23
+ src = "_buf = '';"
24
+ buffer = []
25
+ buffer_next = []
26
+
27
+ template.each_node do |node, type|
28
+ if !buffer_next.empty?
29
+ if is_matching_pair?(buffer.last, node)
30
+ buffer.pop
31
+ next
32
+ elsif is_nonpair_tag? node
33
+ next
34
+ else
35
+ buffer << buffer_next
36
+ buffer.flatten!
37
+ buffer_next = []
38
+ end
39
+ end
40
+
41
+ if type == NodeType::CONTROL
42
+ buffer_next = process_instruction(node)
43
+ else
44
+ buffer << process_instruction(node)
45
+ buffer.flatten!
46
+ end
47
+ end
48
+
49
+ buffer.each { |line| src << line.to_buf }
50
+ src << "\n_buf.to_s\n"
51
+ end
52
+
53
+ def process_instruction text
54
+ text = text.strip
55
+ pos = 0
56
+ src = []
57
+
58
+ text.scan(EMBEDDED_PATTERN) do |indicator, code|
59
+ m = Regexp.last_match
60
+ middle = text[pos...m.begin(0)]
61
+ pos = m.end(0)
62
+ src << Line.text(middle) unless middle.empty?
63
+
64
+ if !indicator # <% %>
65
+ src << Line.code(code)
66
+ else # <%= %>
67
+ src << Line.string(code)
68
+ end
69
+ end
70
+
71
+ rest = pos == 0 ? text : text[pos..-1]
72
+
73
+ src << Line.text(rest) unless rest.nil? or rest.empty?
74
+ src
75
+ end
76
+
77
+ def is_nonpair_tag? tag
78
+ tag =~ /<.+?\/>/
79
+ end
80
+
81
+ def is_matching_pair? open, close
82
+ open = open.to_s.strip
83
+ close = close.to_s.strip
84
+
85
+ close == "</#{open[1, close.length - 3]}>"
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,27 @@
1
+ require 'zip/zip'
2
+ require 'fileutils'
3
+
4
+ module Serenity
5
+ class Template
6
+ attr_accessor :template
7
+
8
+ def initialize(template, output)
9
+ FileUtils.cp(template, output)
10
+ @template = output
11
+ end
12
+
13
+ def process context
14
+ Zip::ZipFile.open(@template) do |zipfile|
15
+ content = zipfile.read('content.xml')
16
+ odteruby = OdtEruby.new(XmlReader.new(content))
17
+ out = odteruby.evaluate context
18
+
19
+ file = Tempfile.new("serenity")
20
+ file << out
21
+ file.close
22
+
23
+ zipfile.replace('content.xml', file.path)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ module Serenity
2
+ class XmlReader
3
+
4
+ def initialize src
5
+ @src = src
6
+ end
7
+
8
+ def each_node
9
+ last_match_pos = 0
10
+
11
+ @src.scan(/<.*?>/) do |node|
12
+ m = Regexp.last_match
13
+ if m.begin(0) > last_match_pos + 1
14
+ text = @src[last_match_pos...m.begin(0)]
15
+ yield text.strip, node_type(text) if text.gsub(/\s+/, '') != ''
16
+ end
17
+
18
+ last_match_pos = m.end(0)
19
+ yield node, NodeType::TAG
20
+ end
21
+ end
22
+
23
+ def node_type text
24
+ if text =~ /\s*\{%[^=#].+?%\}\s*/
25
+ NodeType::CONTROL
26
+ else
27
+ NodeType::TEMPLATE
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,36 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{serenity-odt}
5
+ s.version = "0.1.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Tomas Kramar"]
9
+ s.date = %q{2010-02-18}
10
+ s.description = %q{ Embedded ruby for OpenOffice Text Document (.odt) files. You provide an .odt template
11
+ with ruby code in a special markup and the data, and Serenity generates the document.
12
+ Very similar to .erb files.
13
+ }
14
+ s.email = %q{kramar.tomas@gmail.com}
15
+ s.files = ["lib/serenity/debug.rb", "lib/serenity/generator.rb", "lib/serenity/line.rb", "lib/serenity/node_type.rb", "lib/serenity/odteruby.rb", "lib/serenity/template.rb", "lib/serenity/xml_reader.rb", "lib/serenity.rb", "README.md", "Rakefile", "serenity-odt.gemspec", "LICENSE", "spec/generator_spec.rb", "spec/odteruby_spec.rb", "spec/spec_helper.rb", "spec/support/matchers/be_a_document.rb", "spec/template_spec.rb", "spec/xml_reader_spec.rb", "fixtures/advanced.odt", "fixtures/loop.odt", "fixtures/loop_table.odt", "fixtures/table_rows.odt", "fixtures/variables.odt"]
16
+ s.require_paths = ["lib"]
17
+ s.rubygems_version = %q{1.3.5}
18
+ s.summary = %q{Embedded ruby for OpenOffice Text Document (.odt) files}
19
+ s.test_files = ["spec/generator_spec.rb", "spec/odteruby_spec.rb", "spec/spec_helper.rb", "spec/support/matchers/be_a_document.rb", "spec/template_spec.rb", "spec/xml_reader_spec.rb", "fixtures/advanced.odt", "fixtures/loop.odt", "fixtures/loop_table.odt", "fixtures/table_rows.odt", "fixtures/variables.odt"]
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 3
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ s.add_runtime_dependency(%q<rubyzip>, [">= 0.9.1"])
27
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
28
+ else
29
+ s.add_dependency(%q<rubyzip>, [">= 0.9.1"])
30
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
31
+ end
32
+ else
33
+ s.add_dependency(%q<rubyzip>, [">= 0.9.1"])
34
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
35
+ end
36
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Serenity
4
+ describe Generator do
5
+ it 'should make context from instance variables and run the provided template' do
6
+ class GeneratorClient
7
+ include Generator
8
+
9
+ def generate_odt
10
+ @crew = ['Mal', 'Inara', 'Wash', 'Zoe']
11
+
12
+ render_odt fixture('loop.odt')
13
+ end
14
+ end
15
+
16
+ client = GeneratorClient.new
17
+ lambda { client.generate_odt }.should_not raise_error
18
+ fixture('loop_output.odt').should be_a_document
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,102 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Serenity
4
+
5
+ describe OdtEruby do
6
+ before(:each) do
7
+ name = 'test_name'
8
+ type = 'test_type'
9
+ rows = []
10
+ rows << Ship.new('test_name_1', 'test_type_1')
11
+ rows << Ship.new('test_name_2', 'test_type_2')
12
+ @context = binding
13
+ end
14
+
15
+ def squeeze text
16
+ text.inject('') { |memo, line| memo += line.strip } unless text.nil?
17
+ end
18
+
19
+ it 'should replace variables with values from context' do
20
+ template = <<-EOF
21
+ <text:p text:style-name="Text_1_body">{%= name %}</text:p>
22
+ <text:p text:style-name="Text_1_body">{%= type %}</text:p>
23
+ <text:p text:style-name="Text_1_body"/>
24
+ EOF
25
+
26
+ expected = <<-EOF
27
+ <text:p text:style-name="Text_1_body">test_name</text:p>
28
+ <text:p text:style-name="Text_1_body">test_type</text:p>
29
+ <text:p text:style-name="Text_1_body"/>
30
+ EOF
31
+
32
+ content = OdtEruby.new(XmlReader.new template)
33
+ result = content.evaluate @context
34
+
35
+ squeeze(expected).should == squeeze(result)
36
+ end
37
+
38
+ it 'should replace multiple variables on one line' do
39
+ template = '<text:p text:style-name="Text_1_body">{%= type %} and {%= name %}</text:p>'
40
+ expected = '<text:p text:style-name="Text_1_body">test_type and test_name</text:p>'
41
+
42
+ content = OdtEruby.new(XmlReader.new template)
43
+ result = content.evaluate @context
44
+
45
+ squeeze(expected).should == squeeze(result)
46
+ end
47
+ =begin
48
+ should 'replace a LOOP construct with variables' do
49
+ template = <<-EOF
50
+ <text:p text:style-name="Text_1_body">{% for row in rows do %}</text:p>
51
+ <text:p text:style-name="Text_1_body">{%= row.name %}</text:p>
52
+ <text:p text:style-name="Text_1_body">{%= row.type %}</text:p>
53
+ <text:p text:style-name="Text_1_body">{% end %}</text:p>
54
+ EOF
55
+
56
+ expected = <<-EOF
57
+ <text:p text:style-name="Text_1_body">test_name_1</text:p>
58
+ <text:p text:style-name="Text_1_body">test_type_1</text:p>
59
+ <text:p text:style-name="Text_1_body">test_name_2</text:p>
60
+ <text:p text:style-name="Text_1_body">test_type_2</text:p>
61
+ EOF
62
+
63
+ content = OdtEruby.new(XmlReader.new template)
64
+ result = content.evaluate @context
65
+ assert_equal expected, result
66
+ end
67
+ =end
68
+
69
+ it 'should remove empty tags after a control structure processing' do
70
+ template = <<-EOF
71
+ <table:table style="Table_1">
72
+ <table:row style="Table_1_A1">
73
+ <table:cell style="Table_1_A1_cell">
74
+ {% for row in rows do %}
75
+ </table:cell>
76
+ </table:row>
77
+ <text:p text:style-name="Text_1_body">{%= row.name %}</text:p>
78
+ <text:p text:style-name="Text_1_body">{%= row.type %}</text:p>
79
+ <table:row style="Table_1_A1">
80
+ <table:cell style="Table_1_A1_cell">
81
+ {% end %}
82
+ </table:cell>
83
+ </table:row>
84
+ </table:table>
85
+ EOF
86
+
87
+ expected = <<-EOF
88
+ <table:table style="Table_1">
89
+ <text:p text:style-name="Text_1_body">test_name_1</text:p>
90
+ <text:p text:style-name="Text_1_body">test_type_1</text:p>
91
+ <text:p text:style-name="Text_1_body">test_name_2</text:p>
92
+ <text:p text:style-name="Text_1_body">test_type_2</text:p>
93
+ </table:table>
94
+ EOF
95
+
96
+ content = OdtEruby.new(XmlReader.new template)
97
+ result = content.evaluate @context
98
+
99
+ squeeze(expected).should == squeeze(result)
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,12 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
+
3
+ require 'rubygems'
4
+ require 'serenity'
5
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
6
+
7
+ Ship = Struct.new(:name, :type)
8
+ Person = Struct.new(:name, :skill)
9
+
10
+ def fixture name
11
+ File.join(File.dirname(__FILE__), '..', 'fixtures', name)
12
+ end
@@ -0,0 +1,16 @@
1
+ module Serenity
2
+ Spec::Matchers.define :be_a_document do
3
+ match do |actual|
4
+ File.exists? actual
5
+ end
6
+
7
+ failure_message_for_should do |actual|
8
+ "expected that a file #{actual} would exist"
9
+ end
10
+
11
+ failure_message_for_should_not do |actual|
12
+ "expected that a file #{actual} would not exist"
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,48 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'fileutils'
3
+
4
+ module Serenity
5
+
6
+ describe Template do
7
+
8
+ after(:each) do
9
+ FileUtils.rm(Dir['*.odt'])
10
+ end
11
+
12
+ it "should process a document with simple variable substitution" do
13
+ name = 'Malcolm Reynolds'
14
+ title = 'captain'
15
+
16
+ template = Template.new(fixture('variables.odt'), 'output_variables.odt')
17
+ lambda {template.process binding}.should_not raise_error
18
+ end
19
+
20
+ it "should unroll a simple for loop" do
21
+ crew = %w{'River', 'Jayne', 'Wash'}
22
+
23
+ template = Template.new(fixture('loop.odt'), 'output_loop.odt')
24
+ lambda {template.process binding}.should_not raise_error
25
+ end
26
+
27
+ it "should unroll an advanced loop with tables" do
28
+ ships = [Ship.new('Firefly', 'transport'), Ship.new('Colonial', 'battle')]
29
+
30
+ template = Template.new(fixture('loop_table.odt'), 'output_loop_table.odt')
31
+ lambda {template.process binding}.should_not raise_error
32
+ end
33
+
34
+ it "should process an advanced document" do
35
+ persons = [Person.new('Malcolm', 'captain'), Person.new('River', 'psychic'), Person.new('Jay', 'gunslinger')]
36
+
37
+ template = Template.new(fixture('advanced.odt'), 'output_advanced.odt')
38
+ lambda {template.process binding}.should_not raise_error
39
+ end
40
+
41
+ it "should loop and generate table rows" do
42
+ ships = [Ship.new('Firefly', 'transport'), Ship.new('Colonial', 'battle')]
43
+
44
+ template = Template.new(fixture('table_rows.odt'), 'output_table_rows.odt')
45
+ lambda {template.process binding}.should_not raise_error
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Serenity
4
+
5
+ Node = Struct.new(:text, :type)
6
+
7
+ describe XmlReader do
8
+ it "should stream the xml, tag by tag" do
9
+ xml = <<-EOF
10
+ <?xml version="1.0" encoding="UTF-8"?><office:document-content><office:scripts/>
11
+ <office:body><text:p style="Standard">This is a sentence</text:p><text:s>{%= yeah %}</text:s></office:body>
12
+ {% for row in rows %}
13
+ </office:document-content>
14
+ EOF
15
+
16
+ expected = [Node.new('<?xml version="1.0" encoding="UTF-8"?>', NodeType::TAG),
17
+ Node.new('<office:document-content>', NodeType::TAG),
18
+ Node.new('<office:scripts/>', NodeType::TAG),
19
+ Node.new('<office:body>', NodeType::TAG),
20
+ Node.new('<text:p style="Standard">', NodeType::TAG),
21
+ Node.new('This is a sentence', NodeType::TEMPLATE),
22
+ Node.new('</text:p>', NodeType::TAG),
23
+ Node.new('<text:s>', NodeType::TAG),
24
+ Node.new('{%= yeah %}', NodeType::TEMPLATE),
25
+ Node.new('</text:s>', NodeType::TAG),
26
+ Node.new('</office:body>', NodeType::TAG),
27
+ Node.new('{% for row in rows %}', NodeType::CONTROL),
28
+ Node.new('</office:document-content>', NodeType::TAG)]
29
+
30
+ reader = XmlReader.new xml
31
+
32
+ idx = 0
33
+ reader.each_node do |node, type|
34
+ expected[idx].text.should == node
35
+ expected[idx].type.should == type
36
+ idx += 1
37
+ end
38
+ end
39
+ end
40
+ end
41
+
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: serenity-odt
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Tomas Kramar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-18 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubyzip
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.2.9
34
+ version:
35
+ description: " Embedded ruby for OpenOffice Text Document (.odt) files. You provide an .odt template\n with ruby code in a special markup and the data, and Serenity generates the document.\n Very similar to .erb files.\n"
36
+ email: kramar.tomas@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - lib/serenity/debug.rb
45
+ - lib/serenity/generator.rb
46
+ - lib/serenity/line.rb
47
+ - lib/serenity/node_type.rb
48
+ - lib/serenity/odteruby.rb
49
+ - lib/serenity/template.rb
50
+ - lib/serenity/xml_reader.rb
51
+ - lib/serenity.rb
52
+ - README.md
53
+ - Rakefile
54
+ - serenity-odt.gemspec
55
+ - LICENSE
56
+ - spec/generator_spec.rb
57
+ - spec/odteruby_spec.rb
58
+ - spec/spec_helper.rb
59
+ - spec/support/matchers/be_a_document.rb
60
+ - spec/template_spec.rb
61
+ - spec/xml_reader_spec.rb
62
+ - fixtures/advanced.odt
63
+ - fixtures/loop.odt
64
+ - fixtures/loop_table.odt
65
+ - fixtures/table_rows.odt
66
+ - fixtures/variables.odt
67
+ has_rdoc: true
68
+ homepage:
69
+ licenses: []
70
+
71
+ post_install_message:
72
+ rdoc_options: []
73
+
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: "0"
87
+ version:
88
+ requirements: []
89
+
90
+ rubyforge_project:
91
+ rubygems_version: 1.3.5
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: Embedded ruby for OpenOffice Text Document (.odt) files
95
+ test_files:
96
+ - spec/generator_spec.rb
97
+ - spec/odteruby_spec.rb
98
+ - spec/spec_helper.rb
99
+ - spec/support/matchers/be_a_document.rb
100
+ - spec/template_spec.rb
101
+ - spec/xml_reader_spec.rb
102
+ - fixtures/advanced.odt
103
+ - fixtures/loop.odt
104
+ - fixtures/loop_table.odt
105
+ - fixtures/table_rows.odt
106
+ - fixtures/variables.odt