clamsy 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY.txt +4 -0
- data/README.rdoc +175 -27
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/clamsy.gemspec +9 -2
- data/lib/clamsy.rb +13 -3
- data/spec/clamsy_spec.rb +17 -8
- data/spec/data/clamsy.png +0 -0
- data/spec/data/clamsy2.png +0 -0
- data/spec/data/picture_example.odt +0 -0
- data/spec/data/picture_example.pdf +0 -0
- data/spec/spec_helper.rb +13 -1
- metadata +23 -5
data/HISTORY.txt
CHANGED
data/README.rdoc
CHANGED
@@ -4,56 +4,204 @@ Ruby wrapper for generating a single pdf for multiple contexts from an odt templ
|
|
4
4
|
|
5
5
|
clamsy = clumsy + shellish
|
6
6
|
| |
|
7
|
-
| |-- under the hood, we are making system calls
|
8
|
-
|
|
7
|
+
| |-- under the hood, we are making system calls to ooffice &
|
8
|
+
| cups server needs to be running
|
9
9
|
|
|
10
|
-
|
10
|
+
|-- setup isn't straight forward, need to install a couple of packages
|
11
11
|
(how bad it is depends on ur platform) & even manual setting up of
|
12
|
-
cups printer is needed
|
12
|
+
cups-pdf printer is needed
|
13
13
|
|
14
|
-
==
|
14
|
+
== 1. Basics
|
15
15
|
|
16
|
-
|
16
|
+
A template odt is just an ordinary odt (http://en.wikipedia.org/wiki/OpenDocument).
|
17
|
+
In order for it to function as a template, we just need to decorate it (just use
|
18
|
+
openoffice, pls don't buy ms office for that) with placeholders & embedded ruby code.
|
19
|
+
|
20
|
+
Under the hood, clamsy is using a slightly hacked version of the awesome tenjin
|
21
|
+
template engine (http://www.kuwata-lab.com/tenjin) to do the rendering. The following
|
22
|
+
is all u need to know to write odt templates:
|
23
|
+
|
24
|
+
* '{? ... ?}' represents embedded Ruby statement (this differs from vanilla tenjin)
|
25
|
+
* '#{ ... }' represents embedded Ruby expression
|
26
|
+
* '${ ... }' represents embedded Ruby expression which is to be escaped
|
27
|
+
(eg. '& < > "' are escaped to '& < > "')
|
28
|
+
|
29
|
+
== 2. Examples
|
30
|
+
|
31
|
+
=== 2.1. Text Replacement Example
|
32
|
+
|
33
|
+
Template Odt:
|
34
|
+
|
35
|
+
--------------------------------------------
|
36
|
+
#{@company_full_name}
|
37
|
+
#{@company_address_line_1}
|
38
|
+
#{@company_address_line_2}
|
39
|
+
|
40
|
+
S/N Item Description Amount (SGD)
|
41
|
+
{? @items.each_with_index do |item, i| ?}
|
42
|
+
#{i+1} #{item.description} #{amount}
|
43
|
+
{? end ?}
|
44
|
+
Total #{total}
|
45
|
+
----------------------------------- Page 1 -
|
46
|
+
|
47
|
+
Code:
|
48
|
+
|
49
|
+
class Item
|
50
|
+
attr_reader :description, :amount
|
51
|
+
def initialize(description, amount)
|
52
|
+
@description, @amount = description, amount
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
items = [
|
57
|
+
Item.new('Shells (x2 Bags)', 10),
|
58
|
+
Item.new('Clams (x2 Bags)', 20)
|
59
|
+
]
|
60
|
+
|
61
|
+
context = {
|
62
|
+
:company_full_name => 'Monster Inc',
|
63
|
+
:company_address_line_1 => 'Planet Mars, Street xyz,',
|
64
|
+
:company_address_line_2 => 'Postal Code 009900',
|
65
|
+
:items => items,
|
66
|
+
:total => items.inject(0) {|sum, item| sum + item.amount }
|
67
|
+
}
|
68
|
+
|
69
|
+
Clamsy.process(
|
70
|
+
context,
|
71
|
+
path_to_template_odt, # eg. '/tmp/invoice.odt'
|
72
|
+
path_to_final_pdf, # eg. '/tmp/invoice.pdf'
|
73
|
+
)
|
74
|
+
|
75
|
+
Generated Pdf:
|
76
|
+
|
77
|
+
--------------------------------------------
|
78
|
+
Monster Inc
|
79
|
+
Planet Mars, Street xyz,
|
80
|
+
Postal Code 009900
|
81
|
+
|
82
|
+
S/N Item Description Amount (SGD)
|
83
|
+
|
84
|
+
1 Shells (x2 Bags) 10
|
85
|
+
2 Clams (x2 Bags) 20
|
86
|
+
|
87
|
+
Total 30
|
88
|
+
----------------------------------- Page 1 -
|
89
|
+
|
90
|
+
=== 2.2: Multiple Contexts Example
|
91
|
+
|
92
|
+
Taking the above example one step further, if we have multiple contexts:
|
93
|
+
|
94
|
+
items << Item.new('Shrimps (x2 Bags)', 15)
|
95
|
+
items << Item.new('Prawns (x2 Bags)', 25)
|
96
|
+
|
97
|
+
contexts = [{
|
98
|
+
:company_full_name => 'Monster Inc',
|
99
|
+
:company_address_line_1 => 'Planet Mars, Street xyz,',
|
100
|
+
:company_address_line_2 => 'Postal Code 009900',
|
101
|
+
:items => items[0..1],
|
102
|
+
:total => items[0..1].inject(0) {|sum, item| sum + item.amount }
|
103
|
+
}, {
|
104
|
+
:company_full_name => 'Fisherman Inc',
|
105
|
+
:company_address_line_1 => 'Planet Jupiter, Street xyz,',
|
106
|
+
:company_address_line_2 => 'Postal Code 008800',
|
107
|
+
:items => items[2..3],
|
108
|
+
:total => items[2..3].inject(0) {|sum, item| sum + item.amount }
|
109
|
+
}]
|
17
110
|
|
18
111
|
Clamsy.process(
|
19
|
-
|
20
|
-
path_to_template_odt,
|
21
|
-
path_to_final_pdf
|
112
|
+
contexts,
|
113
|
+
path_to_template_odt, # eg. '/tmp/invoice.odt'
|
114
|
+
path_to_final_pdf # eg. '/tmp/invoice.pdf'
|
22
115
|
)
|
23
116
|
|
24
|
-
|
117
|
+
Generated Pdf:
|
118
|
+
|
119
|
+
--------------------------------------------
|
120
|
+
Monster Inc
|
121
|
+
Planet Mars, Street xyz,
|
122
|
+
Postal Code 009900
|
123
|
+
|
124
|
+
S/N Item Description Amount (SGD)
|
125
|
+
|
126
|
+
1 Shells (x2 Bags) 10
|
127
|
+
2 Clams (x2 Bags) 20
|
128
|
+
|
129
|
+
Total 30
|
130
|
+
----------------------------------- Page 1 -
|
131
|
+
--------------------------------------------
|
132
|
+
Fisherman Inc
|
133
|
+
Planet Jupiter, Street xyz,
|
134
|
+
Postal Code 008800
|
135
|
+
|
136
|
+
S/N Item Description Amount (SGD)
|
137
|
+
|
138
|
+
1 Shrimps (x2 Bags) 15
|
139
|
+
2 Prawns (x2 Bags) 25
|
140
|
+
|
141
|
+
Total 40
|
142
|
+
----------------------------------- Page 1 -
|
143
|
+
|
144
|
+
As you can see, (whether you like it or not) the pages are merely concatenated
|
145
|
+
together to form a single pdf !!
|
146
|
+
|
147
|
+
=== 2.3: Image Replacement Example
|
148
|
+
|
149
|
+
It is possible to replace images in an odt file, a useful feature if u need to insert
|
150
|
+
digital signature into the final pdf. To acheive this, u have to:
|
151
|
+
* insert a placeholder image into the odt file,
|
152
|
+
* resize & move it to your heart content
|
153
|
+
* right click on the picture, under [Picture ...]/[Options], assign a unique value
|
154
|
+
for [Name]
|
155
|
+
|
156
|
+
Template Odt:
|
157
|
+
|
158
|
+
--------------------------------------------
|
159
|
+
~~~~~~~~~~~~~~~~~~
|
160
|
+
Hey | nice_guy_image |
|
161
|
+
~~~~~~~~~~~~~~~~~~
|
162
|
+
|
163
|
+
This is a gentle reminder that i still
|
164
|
+
owe you some money ...
|
165
|
+
|
166
|
+
~~~~~~~~~~~~~~~~~~~~~~
|
167
|
+
| my_signature_image |
|
168
|
+
~~~~~~~~~~~~~~~~~~~~~~
|
169
|
+
----------------------------------- Page 1 -
|
170
|
+
|
171
|
+
Assuming 'nice_guy_image' & 'my_signature_image' as names of the images, the following
|
172
|
+
code does the appropriate replacing of images:
|
25
173
|
|
26
174
|
Clamsy.process(
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
path_to_template_odt
|
32
|
-
path_to_final_pdf
|
175
|
+
context = {:_pictures => {
|
176
|
+
:nice_guy_image => path_to_avatar_image, # eg. '/tmp/handsome.png'
|
177
|
+
:my_signature_image => path_to_signature_image # eg. '/tmp/signature.png'
|
178
|
+
}},
|
179
|
+
path_to_template_odt # eg. '/tmp/confession.odt'
|
180
|
+
path_to_final_pdf # eg. '/tmp/confession.pdf'
|
33
181
|
)
|
34
182
|
|
35
|
-
== Pre-requisites
|
183
|
+
== 3. Pre-requisites
|
36
184
|
|
37
|
-
|
185
|
+
=== 3.1. Archlinux
|
38
186
|
|
39
|
-
|
40
|
-
|
187
|
+
* Installing packages:
|
188
|
+
$ sudo pacman -S ghostscript cups cups-pdf go-openoffice
|
41
189
|
|
42
|
-
|
43
|
-
|
190
|
+
* Setting up the cups-pdf virtual printer by following instructions @
|
191
|
+
http://wiki.archlinux.org/index.php/CUPS#Configuring_CUPS-PDF_virtual_printer
|
44
192
|
|
45
|
-
|
46
|
-
|
193
|
+
* Making sure cups is running:
|
194
|
+
$ sudo /etc/rc.d/cups start
|
47
195
|
|
48
|
-
|
196
|
+
=== 3.2. Ubuntu (to-be-updated)
|
49
197
|
|
50
|
-
|
198
|
+
=== 3.3. Mac (to-be-updated)
|
51
199
|
|
52
200
|
== TODO
|
53
201
|
|
54
202
|
* add support for configuration, eg. Clamsy.configure {|config| ... }
|
55
203
|
|
56
|
-
* automate cups-pdf printer setup
|
204
|
+
* automate cups-pdf printer setup or have ooffice directly export odt to pdf
|
57
205
|
|
58
206
|
* avoid making system call to 'ooffice'
|
59
207
|
|
data/Rakefile
CHANGED
@@ -12,6 +12,7 @@ begin
|
|
12
12
|
gem.authors = ["NgTzeYang"]
|
13
13
|
gem.add_dependency "rubyzip", "= 0.9.4"
|
14
14
|
gem.add_dependency "rghost", "= 0.8.7.2"
|
15
|
+
gem.add_dependency "nokogiri", "= 1.4.1"
|
15
16
|
gem.add_development_dependency "bacon", ">= 1.1.0"
|
16
17
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
18
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.3
|
data/clamsy.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{clamsy}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.3"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["NgTzeYang"]
|
12
|
-
s.date = %q{2010-04-
|
12
|
+
s.date = %q{2010-04-25}
|
13
13
|
s.description = %q{}
|
14
14
|
s.email = %q{ngty77@gmail.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -28,12 +28,16 @@ Gem::Specification.new do |s|
|
|
28
28
|
"lib/clamsy.rb",
|
29
29
|
"lib/clamsy/tenjin.rb",
|
30
30
|
"spec/clamsy_spec.rb",
|
31
|
+
"spec/data/clamsy.png",
|
32
|
+
"spec/data/clamsy2.png",
|
31
33
|
"spec/data/embedded_ruby_example.odt",
|
32
34
|
"spec/data/embedded_ruby_example.pdf",
|
33
35
|
"spec/data/escaped_text_example.odt",
|
34
36
|
"spec/data/escaped_text_example.pdf",
|
35
37
|
"spec/data/multiple_contexts_example.odt",
|
36
38
|
"spec/data/multiple_contexts_example.pdf",
|
39
|
+
"spec/data/picture_example.odt",
|
40
|
+
"spec/data/picture_example.pdf",
|
37
41
|
"spec/data/plain_text_example.odt",
|
38
42
|
"spec/data/plain_text_example.pdf",
|
39
43
|
"spec/spec_helper.rb"
|
@@ -55,15 +59,18 @@ Gem::Specification.new do |s|
|
|
55
59
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
56
60
|
s.add_runtime_dependency(%q<rubyzip>, ["= 0.9.4"])
|
57
61
|
s.add_runtime_dependency(%q<rghost>, ["= 0.8.7.2"])
|
62
|
+
s.add_runtime_dependency(%q<nokogiri>, ["= 1.4.1"])
|
58
63
|
s.add_development_dependency(%q<bacon>, [">= 1.1.0"])
|
59
64
|
else
|
60
65
|
s.add_dependency(%q<rubyzip>, ["= 0.9.4"])
|
61
66
|
s.add_dependency(%q<rghost>, ["= 0.8.7.2"])
|
67
|
+
s.add_dependency(%q<nokogiri>, ["= 1.4.1"])
|
62
68
|
s.add_dependency(%q<bacon>, [">= 1.1.0"])
|
63
69
|
end
|
64
70
|
else
|
65
71
|
s.add_dependency(%q<rubyzip>, ["= 0.9.4"])
|
66
72
|
s.add_dependency(%q<rghost>, ["= 0.8.7.2"])
|
73
|
+
s.add_dependency(%q<nokogiri>, ["= 1.4.1"])
|
67
74
|
s.add_dependency(%q<bacon>, [">= 1.1.0"])
|
68
75
|
end
|
69
76
|
end
|
data/lib/clamsy.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'ftools'
|
2
2
|
require 'digest/md5'
|
3
3
|
require 'tempfile'
|
4
|
+
require 'nokogiri'
|
4
5
|
require 'zip/zip'
|
5
6
|
require 'clamsy/tenjin'
|
6
7
|
require 'rghost'
|
@@ -47,9 +48,10 @@ module Clamsy
|
|
47
48
|
|
48
49
|
def render(context)
|
49
50
|
@context_id = Digest::MD5.hexdigest(context.to_s)
|
50
|
-
Zip::ZipFile.open(working_odt.path) do
|
51
|
-
zip.select {|entry| entry.file? && entry.to_s =~ /\.xml$/ }.each do |entry|
|
52
|
-
zip.get_output_stream(entry.to_s) {|io| io.write(workers[entry].render(context)) }
|
51
|
+
Zip::ZipFile.open(working_odt.path) do |@zip|
|
52
|
+
@zip.select {|entry| entry.file? && entry.to_s =~ /\.xml$/ }.each do |entry|
|
53
|
+
@zip.get_output_stream(entry.to_s) {|io| io.write(workers[entry].render(context)) }
|
54
|
+
replace_pictures(entry, context[:_pictures] || {})
|
53
55
|
end
|
54
56
|
end
|
55
57
|
working_odt
|
@@ -57,6 +59,14 @@ module Clamsy
|
|
57
59
|
|
58
60
|
private
|
59
61
|
|
62
|
+
def replace_pictures(entry, pictures)
|
63
|
+
xpaths = lambda {|name| %\//drawframe[@drawname="#{name}"]/drawimage/@xlinkhref\ }
|
64
|
+
doc = Nokogiri::XML(entry.get_input_stream.read.gsub(':','')) # Hack to avoid namespace error
|
65
|
+
pictures.each do |name, path|
|
66
|
+
(node = doc.xpath(xpaths[name])[0]) && @zip.replace(node.value, path)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
60
70
|
def working_odt
|
61
71
|
(@working_odts ||= {})[@context_id] ||=
|
62
72
|
begin
|
data/spec/clamsy_spec.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
-
require 'spec_helper'
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
2
|
|
3
3
|
describe "Clamsy" do
|
4
4
|
|
5
5
|
behaves_like 'has standard files support'
|
6
6
|
|
7
7
|
before do
|
8
|
-
@
|
8
|
+
@check_processing_yields_content = lambda do |contexts, example|
|
9
9
|
generated_pdf = tmp_file('clamsy_pdf').path
|
10
|
-
expected_content = comparable_content(expected_pdf(example))
|
11
10
|
Clamsy.process(contexts, template_odt(example), generated_pdf)
|
12
|
-
comparable_content(
|
11
|
+
expected_content = comparable_content(expected_pdf(example))
|
12
|
+
generated_content = comparable_content(generated_pdf)
|
13
|
+
generated_content.size.should.equal expected_content.size
|
14
|
+
(generated_content - expected_content).should.equal []
|
13
15
|
end
|
14
16
|
end
|
15
17
|
|
@@ -17,15 +19,22 @@ describe "Clamsy" do
|
|
17
19
|
trash_tmp_files
|
18
20
|
end
|
19
21
|
|
22
|
+
it 'should do picture replacement for matching <draw:frame draw:name="..." />' do
|
23
|
+
@check_processing_yields_content[
|
24
|
+
context = {:_pictures => {:to_be_replaced_pic => data_file('clamsy.png')}},
|
25
|
+
example = :picture
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
20
29
|
it 'should do #{...} plain text replacement' do
|
21
|
-
@
|
30
|
+
@check_processing_yields_content[
|
22
31
|
context = {:someone => 'Peter', :mood => 'Happy'},
|
23
32
|
example = :plain_text
|
24
33
|
]
|
25
34
|
end
|
26
35
|
|
27
36
|
it 'should do ${...} escaped (santized) replacement' do
|
28
|
-
@
|
37
|
+
@check_processing_yields_content[
|
29
38
|
context = {:someone => '<Peter>', :mood => '<Happy>'},
|
30
39
|
example = :escaped_text
|
31
40
|
]
|
@@ -38,14 +47,14 @@ describe "Clamsy" do
|
|
38
47
|
@name, @mood = name, mood
|
39
48
|
end
|
40
49
|
end
|
41
|
-
@
|
50
|
+
@check_processing_yields_content[
|
42
51
|
context = {:everyone => [@someone.new('Peter','Happy'), @someone.new('Jane','Sad')]},
|
43
52
|
example = :embedded_ruby
|
44
53
|
]
|
45
54
|
end
|
46
55
|
|
47
56
|
it 'should concat multiple contexts processing to a single pdf' do
|
48
|
-
@
|
57
|
+
@check_processing_yields_content[
|
49
58
|
contexts = [{:someone => 'Peter', :mood => 'Happy'}, {:someone => 'Jane', :mood => 'Sad'}],
|
50
59
|
example = :multiple_contexts
|
51
60
|
]
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
data/spec/spec_helper.rb
CHANGED
@@ -10,25 +10,37 @@ require 'clamsy'
|
|
10
10
|
|
11
11
|
shared 'has standard files support' do
|
12
12
|
class << self
|
13
|
+
|
14
|
+
INSIGNIFICANT_AND_UNMATCHABLE_PATTERNS = [
|
15
|
+
/^q\[\-?\d+\.?\d*( \-?\d+\.?\d*){5}\]concat\n$/,
|
16
|
+
/^\d+\.?\d*( \d+\.?\d*){3} re\n$/
|
17
|
+
]
|
18
|
+
|
13
19
|
def data_file(file)
|
14
20
|
File.join(File.dirname(__FILE__), 'data', file)
|
15
21
|
end
|
22
|
+
|
16
23
|
def template_odt(name)
|
17
24
|
data_file("#{name}_example.odt")
|
18
25
|
end
|
26
|
+
|
19
27
|
def expected_pdf(name)
|
20
28
|
data_file("#{name}_example.pdf")
|
21
29
|
end
|
30
|
+
|
22
31
|
def comparable_content(file)
|
23
32
|
RGhost::Convert.new(file).to(:ps).read.grep(/^[^%][^%]?/).
|
24
|
-
reject {|line|
|
33
|
+
reject {|line| INSIGNIFICANT_AND_UNMATCHABLE_PATTERNS.any? {|regexp| regexp =~ line } }
|
25
34
|
end
|
35
|
+
|
26
36
|
def trash_tmp_files
|
27
37
|
(@trashable_tmp_files || []).select {|f| f.path }.map(&:unlink)
|
28
38
|
end
|
39
|
+
|
29
40
|
def tmp_file(file_name)
|
30
41
|
((@trashable_tmp_files ||= []) << Tempfile.new(file_name))[-1]
|
31
42
|
end
|
43
|
+
|
32
44
|
end
|
33
45
|
end
|
34
46
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- NgTzeYang
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-04-
|
17
|
+
date: 2010-04-25 00:00:00 +08:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -47,9 +47,23 @@ dependencies:
|
|
47
47
|
type: :runtime
|
48
48
|
version_requirements: *id002
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
50
|
+
name: nokogiri
|
51
51
|
prerelease: false
|
52
52
|
requirement: &id003 !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - "="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 1
|
58
|
+
- 4
|
59
|
+
- 1
|
60
|
+
version: 1.4.1
|
61
|
+
type: :runtime
|
62
|
+
version_requirements: *id003
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: bacon
|
65
|
+
prerelease: false
|
66
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
53
67
|
requirements:
|
54
68
|
- - ">="
|
55
69
|
- !ruby/object:Gem::Version
|
@@ -59,7 +73,7 @@ dependencies:
|
|
59
73
|
- 0
|
60
74
|
version: 1.1.0
|
61
75
|
type: :development
|
62
|
-
version_requirements: *
|
76
|
+
version_requirements: *id004
|
63
77
|
description: ""
|
64
78
|
email: ngty77@gmail.com
|
65
79
|
executables: []
|
@@ -81,12 +95,16 @@ files:
|
|
81
95
|
- lib/clamsy.rb
|
82
96
|
- lib/clamsy/tenjin.rb
|
83
97
|
- spec/clamsy_spec.rb
|
98
|
+
- spec/data/clamsy.png
|
99
|
+
- spec/data/clamsy2.png
|
84
100
|
- spec/data/embedded_ruby_example.odt
|
85
101
|
- spec/data/embedded_ruby_example.pdf
|
86
102
|
- spec/data/escaped_text_example.odt
|
87
103
|
- spec/data/escaped_text_example.pdf
|
88
104
|
- spec/data/multiple_contexts_example.odt
|
89
105
|
- spec/data/multiple_contexts_example.pdf
|
106
|
+
- spec/data/picture_example.odt
|
107
|
+
- spec/data/picture_example.pdf
|
90
108
|
- spec/data/plain_text_example.odt
|
91
109
|
- spec/data/plain_text_example.pdf
|
92
110
|
- spec/spec_helper.rb
|