serenity-odt 0.2.0 → 0.2.3
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.
- checksums.yaml +7 -0
- data/Rakefile +3 -27
- data/lib/serenity/escape_xml.rb +5 -0
- data/lib/serenity/images_processor.rb +32 -0
- data/lib/serenity/line.rb +6 -2
- data/lib/serenity/odteruby.rb +7 -5
- data/lib/serenity/template.rb +18 -2
- data/lib/serenity/xml_reader.rb +3 -3
- data/lib/serenity.rb +1 -0
- metadata +68 -108
- data/fixtures/advanced.odt +0 -0
- data/fixtures/header.odt +0 -0
- data/fixtures/loop.odt +0 -0
- data/fixtures/loop_table.odt +0 -0
- data/fixtures/table_rows.odt +0 -0
- data/fixtures/variables.odt +0 -0
- data/spec/escape_xml_spec.rb +0 -19
- data/spec/generator_spec.rb +0 -25
- data/spec/odteruby_spec.rb +0 -93
- data/spec/spec_helper.rb +0 -12
- data/spec/support/matchers/be_a_document.rb +0 -16
- data/spec/support/matchers/contain_in.rb +0 -20
- data/spec/template_spec.rb +0 -56
- data/spec/xml_reader_spec.rb +0 -41
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 17fd0d1ef98dd78013054dd47ddb91141bd90ee83d1c023160421872f3e2be6b
|
|
4
|
+
data.tar.gz: 2a66ff91bf4b31bea7f20be8cbc804c26562bafacde52e099ce3d3a99e0213c9
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 42f5842bd6dd034d4a65bbc7133eec279c654c2509b9af2fe4fffae053cc16ad8bd24d8027ee5efb71aecb07e770182cd76b29fe1760e70759080cdd288ef60c
|
|
7
|
+
data.tar.gz: a477a692d9afbb4ffea38028ca5c22599a1a3a2c1348bfc68df130203e471c8536e1aedbce21301397244615c65c70b3b714c998e51c24c7e70082197bb338c4
|
data/Rakefile
CHANGED
|
@@ -1,32 +1,8 @@
|
|
|
1
1
|
require 'rake'
|
|
2
|
-
require '
|
|
3
|
-
require 'rake/gempackagetask'
|
|
2
|
+
require 'rspec/core/rake_task'
|
|
4
3
|
|
|
5
4
|
task :default => [:spec]
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
RSpec::Core::RakeTask.new(:spec)
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
s.name = %q{serenity-odt}
|
|
11
|
-
s.version = "0.2.0"
|
|
12
|
-
|
|
13
|
-
s.authors = ["Tomas Kramar"]
|
|
14
|
-
s.description = <<-EOF
|
|
15
|
-
Embedded ruby for OpenOffice Text Document (.odt) files. You provide an .odt template
|
|
16
|
-
with ruby code in a special markup and the data, and Serenity generates the document.
|
|
17
|
-
Very similar to .erb files.
|
|
18
|
-
EOF
|
|
19
|
-
s.email = %q{kramar.tomas@gmail.com}
|
|
20
|
-
s.files = Dir.glob('lib/**/*.rb') + %w{README.md Rakefile LICENSE}
|
|
21
|
-
s.has_rdoc = false
|
|
22
|
-
s.require_paths = ["lib"]
|
|
23
|
-
s.rubygems_version = %q{1.3.5}
|
|
24
|
-
s.summary = %q{Embedded ruby for OpenOffice Text Document (.odt) files}
|
|
25
|
-
s.test_files = Dir.glob('spec/**/*.rb') + Dir.glob('fixtures/*.odt')
|
|
26
|
-
s.add_dependency('rubyzip', '>= 0.9.1')
|
|
27
|
-
s.add_development_dependency('rspec', '>= 1.2.9')
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
Rake::GemPackageTask.new(spec) do |p|
|
|
31
|
-
p.gem_spec = spec
|
|
32
|
-
end
|
|
8
|
+
# Build the gem with: gem build serenity-odt.gemspec
|
data/lib/serenity/escape_xml.rb
CHANGED
|
@@ -3,6 +3,11 @@ class String
|
|
|
3
3
|
mgsub!([[/&/, '&'], [/</, '<'], [/>/, '>']])
|
|
4
4
|
end
|
|
5
5
|
|
|
6
|
+
def convert_newlines
|
|
7
|
+
gsub!("\n", '<text:line-break/>')
|
|
8
|
+
self
|
|
9
|
+
end
|
|
10
|
+
|
|
6
11
|
def mgsub!(key_value_pairs=[].freeze)
|
|
7
12
|
regexp_fragments = key_value_pairs.collect { |k,v| k }
|
|
8
13
|
gsub!(Regexp.union(*regexp_fragments)) do |match|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Serenity
|
|
2
|
+
class ImagesProcessor
|
|
3
|
+
include Debug
|
|
4
|
+
|
|
5
|
+
IMAGE_DIR_NAME = "Pictures"
|
|
6
|
+
|
|
7
|
+
def initialize(xml_content, context)
|
|
8
|
+
@replacements = []
|
|
9
|
+
@images = eval('@images', context)
|
|
10
|
+
@xml_content = xml_content
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def generate_replacements
|
|
14
|
+
require 'nokogiri'
|
|
15
|
+
|
|
16
|
+
if @images && @images.kind_of?(Hash)
|
|
17
|
+
xml_data = Nokogiri::XML(@xml_content)
|
|
18
|
+
|
|
19
|
+
@images.each do |image_name, replacement_path|
|
|
20
|
+
if node = xml_data.xpath("//draw:frame[@draw:name='#{image_name}']/draw:image").first
|
|
21
|
+
placeholder_path = node.attribute('href').value
|
|
22
|
+
odt_image_path = ::File.join(IMAGE_DIR_NAME, ::File.basename(placeholder_path))
|
|
23
|
+
|
|
24
|
+
@replacements << [odt_image_path, replacement_path]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@replacements
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/serenity/line.rb
CHANGED
|
@@ -44,13 +44,17 @@ module Serenity
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def escape_code code
|
|
47
|
-
code.mgsub! [[/'/, "'"], [/>/, '>'], [/</, '<'], [/"/, '"']]
|
|
47
|
+
code.mgsub! [[/'/, "'"], [/>/, '>'], [/</, '<'], [/"/, '"'], [/&/, '&']]
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
class StringLine < CodeLine
|
|
52
52
|
def to_buf
|
|
53
|
-
" _buf << (" << escape_code(@text) << ").to_s.escape_xml;"
|
|
53
|
+
" _buf << (" << escape_code(@text) << ").to_s.escape_xml.convert_newlines;"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def convert_newlines text
|
|
57
|
+
text.gsub("First line", '<text:line-break>')
|
|
54
58
|
end
|
|
55
59
|
end
|
|
56
60
|
|
data/lib/serenity/odteruby.rb
CHANGED
|
@@ -14,6 +14,7 @@ module Serenity
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def evaluate context
|
|
17
|
+
@src = @src.force_encoding Encoding.default_external
|
|
17
18
|
eval(@src, context)
|
|
18
19
|
end
|
|
19
20
|
|
|
@@ -21,6 +22,9 @@ module Serenity
|
|
|
21
22
|
|
|
22
23
|
def convert template
|
|
23
24
|
src = "_buf = '';"
|
|
25
|
+
# `buffer`/`buffer_next` stay flat arrays of Line objects, so appending with `concat`
|
|
26
|
+
# keeps them flat in O(k). (The old `buffer << arr; buffer.flatten!` rescanned the whole
|
|
27
|
+
# buffer on every node, making `convert` O(n^2) in the number of template nodes.)
|
|
24
28
|
buffer = []
|
|
25
29
|
buffer_next = []
|
|
26
30
|
|
|
@@ -32,8 +36,7 @@ module Serenity
|
|
|
32
36
|
elsif is_nonpair_tag? node
|
|
33
37
|
next
|
|
34
38
|
else
|
|
35
|
-
buffer
|
|
36
|
-
buffer.flatten!
|
|
39
|
+
buffer.concat(buffer_next)
|
|
37
40
|
buffer_next = []
|
|
38
41
|
end
|
|
39
42
|
end
|
|
@@ -41,8 +44,7 @@ module Serenity
|
|
|
41
44
|
if type == NodeType::CONTROL
|
|
42
45
|
buffer_next = process_instruction(node)
|
|
43
46
|
else
|
|
44
|
-
buffer
|
|
45
|
-
buffer.flatten!
|
|
47
|
+
buffer.concat(process_instruction(node))
|
|
46
48
|
end
|
|
47
49
|
end
|
|
48
50
|
|
|
@@ -51,7 +53,7 @@ module Serenity
|
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
def process_instruction text
|
|
54
|
-
text = text.strip
|
|
56
|
+
#text = text.strip
|
|
55
57
|
pos = 0
|
|
56
58
|
src = []
|
|
57
59
|
|
data/lib/serenity/template.rb
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
begin
|
|
2
|
+
require 'zip' # rubyzip >= 1.0
|
|
3
|
+
rescue LoadError
|
|
4
|
+
require 'zip/zip' # rubyzip 0.9.x (legacy)
|
|
5
|
+
end
|
|
2
6
|
require 'fileutils'
|
|
7
|
+
require 'tempfile'
|
|
3
8
|
|
|
4
9
|
module Serenity
|
|
10
|
+
# rubyzip renamed Zip::ZipFile to Zip::File in 1.0; support both.
|
|
11
|
+
ZipFile = defined?(::Zip::File) ? ::Zip::File : ::Zip::ZipFile
|
|
12
|
+
|
|
5
13
|
class Template
|
|
6
14
|
attr_accessor :template
|
|
7
15
|
|
|
@@ -12,11 +20,19 @@ module Serenity
|
|
|
12
20
|
|
|
13
21
|
def process context
|
|
14
22
|
tmpfiles = []
|
|
15
|
-
|
|
23
|
+
ZipFile.open(@template) do |zipfile|
|
|
16
24
|
%w(content.xml styles.xml).each do |xml_file|
|
|
17
25
|
content = zipfile.read(xml_file)
|
|
26
|
+
|
|
27
|
+
# Images replacement
|
|
28
|
+
images_replacements = ImagesProcessor.new(content, context).generate_replacements
|
|
29
|
+
images_replacements.each do |r|
|
|
30
|
+
zipfile.replace(r.first, r.last)
|
|
31
|
+
end
|
|
32
|
+
|
|
18
33
|
odteruby = OdtEruby.new(XmlReader.new(content))
|
|
19
34
|
out = odteruby.evaluate(context)
|
|
35
|
+
out.force_encoding Encoding.default_external
|
|
20
36
|
|
|
21
37
|
tmpfiles << (file = Tempfile.new("serenity"))
|
|
22
38
|
file << out
|
data/lib/serenity/xml_reader.rb
CHANGED
|
@@ -2,7 +2,7 @@ module Serenity
|
|
|
2
2
|
class XmlReader
|
|
3
3
|
|
|
4
4
|
def initialize src
|
|
5
|
-
@src = src
|
|
5
|
+
@src = src.force_encoding("UTF-8")
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def each_node
|
|
@@ -10,9 +10,9 @@ module Serenity
|
|
|
10
10
|
|
|
11
11
|
@src.scan(/<.*?>/) do |node|
|
|
12
12
|
m = Regexp.last_match
|
|
13
|
-
if m.begin(0) > last_match_pos
|
|
13
|
+
if m.begin(0) > last_match_pos
|
|
14
14
|
text = @src[last_match_pos...m.begin(0)]
|
|
15
|
-
yield text
|
|
15
|
+
yield text, node_type(text) if text.gsub(/\s+/, '') != ''
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
last_match_pos = m.end(0)
|
data/lib/serenity.rb
CHANGED
metadata
CHANGED
|
@@ -1,136 +1,96 @@
|
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: serenity-odt
|
|
3
|
-
version: !ruby/object:Gem::Version
|
|
4
|
-
|
|
5
|
-
prerelease: false
|
|
6
|
-
segments:
|
|
7
|
-
- 0
|
|
8
|
-
- 2
|
|
9
|
-
- 0
|
|
10
|
-
version: 0.2.0
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.3
|
|
11
5
|
platform: ruby
|
|
12
|
-
authors:
|
|
13
|
-
-
|
|
14
|
-
autorequire:
|
|
6
|
+
authors:
|
|
7
|
+
- kremso
|
|
15
8
|
bindir: bin
|
|
16
9
|
cert_chain: []
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
dependencies:
|
|
21
|
-
- !ruby/object:Gem::Dependency
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
22
13
|
name: rubyzip
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 0.9.1
|
|
19
|
+
type: :runtime
|
|
23
20
|
prerelease: false
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
requirements:
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
27
23
|
- - ">="
|
|
28
|
-
- !ruby/object:Gem::Version
|
|
29
|
-
hash: 57
|
|
30
|
-
segments:
|
|
31
|
-
- 0
|
|
32
|
-
- 9
|
|
33
|
-
- 1
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
34
25
|
version: 0.9.1
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: nokogiri
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.0'
|
|
35
33
|
type: :runtime
|
|
36
|
-
version_requirements: *id001
|
|
37
|
-
- !ruby/object:Gem::Dependency
|
|
38
|
-
name: rspec
|
|
39
34
|
prerelease: false
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.0'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rspec
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
43
44
|
- - ">="
|
|
44
|
-
- !ruby/object:Gem::Version
|
|
45
|
-
|
|
46
|
-
segments:
|
|
47
|
-
- 1
|
|
48
|
-
- 2
|
|
49
|
-
- 9
|
|
50
|
-
version: 1.2.9
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.0'
|
|
51
47
|
type: :development
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '3.0'
|
|
54
|
+
description: Embedded ruby for OpenOffice/LibreOffice Text Document (.odt) files.
|
|
55
|
+
You provide an .odt template with ruby code in a special markup and the data, and
|
|
56
|
+
Serenity generates the document. Very similar to .erb files.
|
|
57
|
+
email: ''
|
|
55
58
|
executables: []
|
|
56
|
-
|
|
57
59
|
extensions: []
|
|
58
|
-
|
|
59
60
|
extra_rdoc_files: []
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
files:
|
|
62
|
+
- LICENSE
|
|
63
|
+
- README.md
|
|
64
|
+
- Rakefile
|
|
65
|
+
- lib/serenity.rb
|
|
62
66
|
- lib/serenity/debug.rb
|
|
63
67
|
- lib/serenity/escape_xml.rb
|
|
64
68
|
- lib/serenity/generator.rb
|
|
69
|
+
- lib/serenity/images_processor.rb
|
|
65
70
|
- lib/serenity/line.rb
|
|
66
71
|
- lib/serenity/node_type.rb
|
|
67
72
|
- lib/serenity/odteruby.rb
|
|
68
73
|
- lib/serenity/template.rb
|
|
69
74
|
- lib/serenity/xml_reader.rb
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
-
|
|
73
|
-
|
|
74
|
-
- spec/escape_xml_spec.rb
|
|
75
|
-
- spec/generator_spec.rb
|
|
76
|
-
- spec/odteruby_spec.rb
|
|
77
|
-
- spec/spec_helper.rb
|
|
78
|
-
- spec/support/matchers/be_a_document.rb
|
|
79
|
-
- spec/support/matchers/contain_in.rb
|
|
80
|
-
- spec/template_spec.rb
|
|
81
|
-
- spec/xml_reader_spec.rb
|
|
82
|
-
- fixtures/advanced.odt
|
|
83
|
-
- fixtures/header.odt
|
|
84
|
-
- fixtures/loop.odt
|
|
85
|
-
- fixtures/loop_table.odt
|
|
86
|
-
- fixtures/table_rows.odt
|
|
87
|
-
- fixtures/variables.odt
|
|
88
|
-
has_rdoc: true
|
|
89
|
-
homepage:
|
|
90
|
-
licenses: []
|
|
91
|
-
|
|
92
|
-
post_install_message:
|
|
75
|
+
homepage: https://github.com/kremso/serenity
|
|
76
|
+
licenses:
|
|
77
|
+
- MIT
|
|
78
|
+
metadata: {}
|
|
93
79
|
rdoc_options: []
|
|
94
|
-
|
|
95
|
-
require_paths:
|
|
80
|
+
require_paths:
|
|
96
81
|
- lib
|
|
97
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
|
-
|
|
99
|
-
requirements:
|
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
|
+
requirements:
|
|
100
84
|
- - ">="
|
|
101
|
-
- !ruby/object:Gem::Version
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
version: "0"
|
|
106
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
|
-
none: false
|
|
108
|
-
requirements:
|
|
85
|
+
- !ruby/object:Gem::Version
|
|
86
|
+
version: 2.6.0
|
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
|
+
requirements:
|
|
109
89
|
- - ">="
|
|
110
|
-
- !ruby/object:Gem::Version
|
|
111
|
-
|
|
112
|
-
segments:
|
|
113
|
-
- 0
|
|
114
|
-
version: "0"
|
|
90
|
+
- !ruby/object:Gem::Version
|
|
91
|
+
version: '0'
|
|
115
92
|
requirements: []
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
specification_version: 3
|
|
121
|
-
summary: Embedded ruby for OpenOffice Text Document (.odt) files
|
|
122
|
-
test_files:
|
|
123
|
-
- spec/escape_xml_spec.rb
|
|
124
|
-
- spec/generator_spec.rb
|
|
125
|
-
- spec/odteruby_spec.rb
|
|
126
|
-
- spec/spec_helper.rb
|
|
127
|
-
- spec/support/matchers/be_a_document.rb
|
|
128
|
-
- spec/support/matchers/contain_in.rb
|
|
129
|
-
- spec/template_spec.rb
|
|
130
|
-
- spec/xml_reader_spec.rb
|
|
131
|
-
- fixtures/advanced.odt
|
|
132
|
-
- fixtures/header.odt
|
|
133
|
-
- fixtures/loop.odt
|
|
134
|
-
- fixtures/loop_table.odt
|
|
135
|
-
- fixtures/table_rows.odt
|
|
136
|
-
- fixtures/variables.odt
|
|
93
|
+
rubygems_version: 4.0.14
|
|
94
|
+
specification_version: 4
|
|
95
|
+
summary: Parse ODT file and substitutes placeholders like ERb.
|
|
96
|
+
test_files: []
|
data/fixtures/advanced.odt
DELETED
|
Binary file
|
data/fixtures/header.odt
DELETED
|
Binary file
|
data/fixtures/loop.odt
DELETED
|
Binary file
|
data/fixtures/loop_table.odt
DELETED
|
Binary file
|
data/fixtures/table_rows.odt
DELETED
|
Binary file
|
data/fixtures/variables.odt
DELETED
|
Binary file
|
data/spec/escape_xml_spec.rb
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
-
|
|
3
|
-
describe String do
|
|
4
|
-
it 'should escape <' do
|
|
5
|
-
'1 < 2'.escape_xml.should == '1 < 2'
|
|
6
|
-
end
|
|
7
|
-
|
|
8
|
-
it 'should escape >' do
|
|
9
|
-
'2 > 1'.escape_xml.should == '2 > 1'
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
it 'should escape &' do
|
|
13
|
-
'1 & 2'.escape_xml.should == '1 & 2'
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
it 'should escape < > &' do
|
|
17
|
-
'1 < 2 && 2 > 1'.escape_xml.should == '1 < 2 && 2 > 1'
|
|
18
|
-
end
|
|
19
|
-
end
|
data/spec/generator_spec.rb
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
|
2
|
-
|
|
3
|
-
module Serenity
|
|
4
|
-
describe Generator do
|
|
5
|
-
after(:each) do
|
|
6
|
-
FileUtils.rm(fixture('loop_output.odt'))
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
it 'should make context from instance variables and run the provided template' do
|
|
10
|
-
class GeneratorClient
|
|
11
|
-
include Serenity::Generator
|
|
12
|
-
|
|
13
|
-
def generate_odt
|
|
14
|
-
@crew = ['Mal', 'Inara', 'Wash', 'Zoe']
|
|
15
|
-
|
|
16
|
-
render_odt fixture('loop.odt')
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
client = GeneratorClient.new
|
|
21
|
-
lambda { client.generate_odt }.should_not raise_error
|
|
22
|
-
fixture('loop_output.odt').should be_a_document
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
data/spec/odteruby_spec.rb
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
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.each_char.inject('') { |memo, line| memo += line.strip } unless text.nil?
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def run_spec template, expected, context=@context
|
|
20
|
-
content = OdtEruby.new(XmlReader.new template)
|
|
21
|
-
result = content.evaluate context
|
|
22
|
-
|
|
23
|
-
squeeze(result).should == squeeze(expected)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
it 'should escape single quotes properly' do
|
|
27
|
-
expected = template = "<text:p>It's a 'quote'</text:p>"
|
|
28
|
-
|
|
29
|
-
run_spec template, expected
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it 'should properly escape special XML characters ("<", ">", "&")' do
|
|
33
|
-
template = "<text:p>{%= description %}</text:p>"
|
|
34
|
-
description = 'This will only hold true if length < 1 && var == true or length > 1000'
|
|
35
|
-
expected = "<text:p>This will only hold true if length < 1 && var == true or length > 1000</text:p>"
|
|
36
|
-
|
|
37
|
-
run_spec template, expected, binding
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
it 'should replace variables with values from context' do
|
|
41
|
-
template = <<-EOF
|
|
42
|
-
<text:p text:style-name="Text_1_body">{%= name %}</text:p>
|
|
43
|
-
<text:p text:style-name="Text_1_body">{%= type %}</text:p>
|
|
44
|
-
<text:p text:style-name="Text_1_body"/>
|
|
45
|
-
EOF
|
|
46
|
-
|
|
47
|
-
expected = <<-EOF
|
|
48
|
-
<text:p text:style-name="Text_1_body">test_name</text:p>
|
|
49
|
-
<text:p text:style-name="Text_1_body">test_type</text:p>
|
|
50
|
-
<text:p text:style-name="Text_1_body"/>
|
|
51
|
-
EOF
|
|
52
|
-
|
|
53
|
-
run_spec template, expected
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
it 'should replace multiple variables on one line' do
|
|
57
|
-
template = '<text:p text:style-name="Text_1_body">{%= type %} and {%= name %}</text:p>'
|
|
58
|
-
expected = '<text:p text:style-name="Text_1_body">test_type and test_name</text:p>'
|
|
59
|
-
|
|
60
|
-
run_spec template, expected
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
it 'should remove empty tags after a control structure processing' do
|
|
64
|
-
template = <<-EOF
|
|
65
|
-
<table:table style="Table_1">
|
|
66
|
-
<table:row style="Table_1_A1">
|
|
67
|
-
<table:cell style="Table_1_A1_cell">
|
|
68
|
-
{% for row in rows do %}
|
|
69
|
-
</table:cell>
|
|
70
|
-
</table:row>
|
|
71
|
-
<text:p text:style-name="Text_1_body">{%= row.name %}</text:p>
|
|
72
|
-
<text:p text:style-name="Text_1_body">{%= row.type %}</text:p>
|
|
73
|
-
<table:row style="Table_1_A1">
|
|
74
|
-
<table:cell style="Table_1_A1_cell">
|
|
75
|
-
{% end %}
|
|
76
|
-
</table:cell>
|
|
77
|
-
</table:row>
|
|
78
|
-
</table:table>
|
|
79
|
-
EOF
|
|
80
|
-
|
|
81
|
-
expected = <<-EOF
|
|
82
|
-
<table:table style="Table_1">
|
|
83
|
-
<text:p text:style-name="Text_1_body">test_name_1</text:p>
|
|
84
|
-
<text:p text:style-name="Text_1_body">test_type_1</text:p>
|
|
85
|
-
<text:p text:style-name="Text_1_body">test_name_2</text:p>
|
|
86
|
-
<text:p text:style-name="Text_1_body">test_type_2</text:p>
|
|
87
|
-
</table:table>
|
|
88
|
-
EOF
|
|
89
|
-
|
|
90
|
-
run_spec template, expected
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
end
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
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
|
|
@@ -1,16 +0,0 @@
|
|
|
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
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
require "zip/zip"
|
|
2
|
-
|
|
3
|
-
module Serenity
|
|
4
|
-
Spec::Matchers.define :contain_in do |xml_file, expected|
|
|
5
|
-
|
|
6
|
-
match do |actual|
|
|
7
|
-
content = Zip::ZipFile.open(actual) { |zip_file| zip_file.read(xml_file) }
|
|
8
|
-
content =~ Regexp.new(".*#{Regexp.escape(expected)}.*")
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
failure_message_for_should do |actual|
|
|
12
|
-
"expected #{actual} to contain the text #{expected}"
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
failure_message_for_should_not do |actual|
|
|
16
|
-
"expected #{actual} to not contain the text #{expected}"
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
end
|
|
20
|
-
end
|
data/spec/template_spec.rb
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
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
|
-
|
|
48
|
-
it "should parse the header" do
|
|
49
|
-
@title = 'captain'
|
|
50
|
-
|
|
51
|
-
template = Template.new(fixture('header.odt'), 'output_header.odt')
|
|
52
|
-
template.process(binding)
|
|
53
|
-
'output_header.odt'.should contain_in('styles.xml', 'captain')
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
data/spec/xml_reader_spec.rb
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
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
|
-
|