serenity-odt 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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