sablon 0.3.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +4 -4
- data/Gemfile.lock +14 -12
- data/README.md +9 -4
- data/lib/sablon/content.rb +10 -5
- data/lib/sablon/processor/document/blocks.rb +40 -4
- data/lib/sablon/template.rb +1 -1
- data/lib/sablon/test/assertions.rb +60 -0
- data/lib/sablon/version.rb +1 -1
- data/misc/TEMPLATE.md +26 -10
- data/sablon.gemspec +5 -3
- data/test/configuration_test.rb +3 -2
- data/test/fixtures/conditionals_sample.docx +0 -0
- data/test/fixtures/conditionals_template.docx +0 -0
- data/test/fixtures/images/svg_sample.svg +6 -0
- data/test/fixtures/images_sample.docx +0 -0
- data/test/fixtures/images_template.docx +0 -0
- data/test/fixtures/svg_images_sample.docx +0 -0
- data/test/fixtures/svg_images_template.docx +0 -0
- data/test/html/ast_builder_test.rb +1 -1
- data/test/sablon_test.rb +25 -2
- data/test/test_helper.rb +3 -56
- metadata +20 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: c83f07a4e1add4db3c1c12d6ffab63e53b7f0acc89e7947efa8cac8a140a35eb
|
4
|
+
data.tar.gz: 23b8e9d2685409410dc418f615c8a23742dbcbc58c3f7a93fcb6a594e84450bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bf3e622843f453b9f2f8b7b9ebbaa18560ec83ecd11ca2386a885bc497ca0149e6e9db64be4a9220a508bf625b7e81748ca636456e03f274d58883efce5453c
|
7
|
+
data.tar.gz: 5bfe0d0737b928420342146c8b920283f0a4c3f9fa32b585871792076df75305048e17c348c44b7ca470408a84e763c2b47ac401a7711cd5219e26270c9d310a
|
data/.travis.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,20 +1,22 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
sablon (0.
|
5
|
-
nokogiri (>= 1.
|
6
|
-
rubyzip (>= 1.
|
4
|
+
sablon (0.4.0)
|
5
|
+
nokogiri (>= 1.8.5)
|
6
|
+
rubyzip (>= 1.3.0)
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: https://rubygems.org/
|
10
10
|
specs:
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
rake (
|
16
|
-
|
17
|
-
|
11
|
+
minitest (5.20.0)
|
12
|
+
nokogiri (1.15.5)
|
13
|
+
racc (~> 1.4)
|
14
|
+
racc (1.7.3)
|
15
|
+
rake (13.1.0)
|
16
|
+
rexml (3.2.6)
|
17
|
+
rubyzip (2.3.2)
|
18
|
+
xml-simple (1.1.9)
|
19
|
+
rexml
|
18
20
|
|
19
21
|
PLATFORMS
|
20
22
|
ruby
|
@@ -22,9 +24,9 @@ PLATFORMS
|
|
22
24
|
DEPENDENCIES
|
23
25
|
bundler (>= 1.6)
|
24
26
|
minitest (~> 5.4)
|
25
|
-
rake (~>
|
27
|
+
rake (~> 13.0)
|
26
28
|
sablon!
|
27
29
|
xml-simple
|
28
30
|
|
29
31
|
BUNDLED WITH
|
30
|
-
|
32
|
+
2.4.15
|
data/README.md
CHANGED
@@ -192,9 +192,10 @@ html_body = <<-HTML.strip
|
|
192
192
|
</table>
|
193
193
|
HTML
|
194
194
|
context = {
|
195
|
-
article: Sablon.content(:html, html_body) }
|
196
|
-
#
|
197
|
-
#
|
195
|
+
article: Sablon.content(:html, html_body) },
|
196
|
+
# Or use html: prefix to make sablon parse the value as HTML.
|
197
|
+
# Does the same as above.
|
198
|
+
'html:article' => html_body
|
198
199
|
}
|
199
200
|
template.render_to_file File.expand_path("~/Desktop/output.docx"), context
|
200
201
|
```
|
@@ -256,10 +257,14 @@ sources such as file paths, URLs, or any object that exposes a `#read`
|
|
256
257
|
method that returns image data. When using a "readable object" if the object
|
257
258
|
doesn't have a `#filename` method then a `filename: '...'` option
|
258
259
|
needs to be added to the `Sablon.content` method call.
|
260
|
+
|
261
|
+
By default the inserted image takes the dimensions of the placeholder. The size of an image can also be defined dynamically by specifying width and height with unit (cm or in) in a properties hash like `properties: {height: "2cm", width: "20cm"}`
|
262
|
+
|
259
263
|
```ruby
|
260
264
|
context = {
|
261
265
|
figure: Sablon.content(:image, 'fixtures/images/c3po.jpg'),
|
262
|
-
figure2: Sablon.content(:image, string_io_obj, filename: 'test.png')
|
266
|
+
figure2: Sablon.content(:image, string_io_obj, filename: 'test.png'),
|
267
|
+
figure3: Sablon.content(:image, string_io_obj, filename: 'test.png', properties: {height: '2cm', width: '2cm'})
|
263
268
|
# alternative method using special key format for simple paths and URLs
|
264
269
|
# 'image:figure' => 'fixtures/images/c3po.jpg'
|
265
270
|
}
|
data/lib/sablon/content.rb
CHANGED
@@ -130,11 +130,16 @@ module Sablon
|
|
130
130
|
# node passed in. Run properties are merged here because of namespace
|
131
131
|
# issues when working with a document fragment
|
132
132
|
def add_siblings_to(node, rpr_tag = nil)
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
# Since Nokogiri 1.11.0 adding siblings is only possible for nodes
|
134
|
+
# with a parent because the parent is used as the context node for
|
135
|
+
# parsing markup.
|
136
|
+
if !node.parent.nil?
|
137
|
+
xml.children.reverse.each do |child|
|
138
|
+
node.add_next_sibling child
|
139
|
+
# merge properties
|
140
|
+
next unless rpr_tag
|
141
|
+
merge_rpr_tags(child, rpr_tag.children)
|
142
|
+
end
|
138
143
|
end
|
139
144
|
end
|
140
145
|
|
@@ -86,7 +86,7 @@ module Sablon
|
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
89
|
-
class ImageBlock <
|
89
|
+
class ImageBlock < Block
|
90
90
|
def self.encloses?(start_field, end_field)
|
91
91
|
start_field.expression.start_with?('@')
|
92
92
|
end
|
@@ -100,12 +100,16 @@ module Sablon
|
|
100
100
|
nodes.each do |node|
|
101
101
|
pic_prop = node.at_xpath('.//pic:cNvPr', pic: 'http://schemas.openxmlformats.org/drawingml/2006/picture')
|
102
102
|
pic_prop.attributes['name'].value = image.name if pic_prop
|
103
|
-
blip =
|
103
|
+
blip = if File.extname(image.name) == '.svg'
|
104
|
+
node.at_xpath('.//asvg:svgBlip', asvg: 'http://schemas.microsoft.com/office/drawing/2016/SVG/main')
|
105
|
+
else
|
106
|
+
node.at_xpath('.//a:blip', a: 'http://schemas.openxmlformats.org/drawingml/2006/main')
|
107
|
+
end
|
104
108
|
blip.attributes['embed'].value = image.local_rid if blip
|
105
109
|
drawing_size = node.at_xpath('.//wp:extent')
|
106
110
|
|
107
|
-
|
108
|
-
|
111
|
+
# if image properties are defined, the size of the placeholder
|
112
|
+
# image should be replaced with the actual values
|
109
113
|
if image.width && image.height
|
110
114
|
drawing_size.attributes['cx'].value = image.width.to_s if drawing_size
|
111
115
|
drawing_size.attributes['cy'].value = image.height.to_s if drawing_size
|
@@ -126,6 +130,28 @@ module Sablon
|
|
126
130
|
super && parent(start_field) == parent(end_field)
|
127
131
|
end
|
128
132
|
|
133
|
+
def process(env)
|
134
|
+
# Create a mock document structure so xpath queries will work
|
135
|
+
# correctly on block level content (i.e. searching for the first
|
136
|
+
# ancestor paragraph)
|
137
|
+
doc_node = Nokogiri::XML::Node.new('document', start_node.document)
|
138
|
+
doc_node.namespace = start_node.parent.namespace
|
139
|
+
p_node = Nokogiri::XML::Node.new('p', doc_node.document)
|
140
|
+
p_node.namespace = start_node.parent.namespace
|
141
|
+
p_node.children = Nokogiri::XML::NodeSet.new(p_node.document,
|
142
|
+
body.map(&:dup))
|
143
|
+
doc_node.children = Nokogiri::XML::NodeSet.new(p_node.document,
|
144
|
+
[p_node])
|
145
|
+
Processor::Document.process doc_node, env
|
146
|
+
|
147
|
+
if p_node.parent.nil?
|
148
|
+
replace_parent_node(doc_node.children)
|
149
|
+
[]
|
150
|
+
else
|
151
|
+
p_node.children
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
129
155
|
def remove_control_elements
|
130
156
|
body.each(&:remove)
|
131
157
|
start_field.remove
|
@@ -139,6 +165,16 @@ module Sablon
|
|
139
165
|
def end_node
|
140
166
|
@end_node ||= end_field.start_node
|
141
167
|
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
# A block level insertion has occurred which must replace the
|
172
|
+
# parent paragraph of the start node.
|
173
|
+
def replace_parent_node(content)
|
174
|
+
node = start_node.ancestors('.//w:p').first
|
175
|
+
content.each { |n| node.add_next_sibling n }
|
176
|
+
node.remove
|
177
|
+
end
|
142
178
|
end
|
143
179
|
end
|
144
180
|
end
|
data/lib/sablon/template.rb
CHANGED
@@ -53,7 +53,7 @@ module Sablon
|
|
53
53
|
|
54
54
|
def render(context, properties = {})
|
55
55
|
# initialize environment
|
56
|
-
@document = Sablon::DOM::Model.new(Zip::File.open(@path))
|
56
|
+
@document = Sablon::DOM::Model.new(Zip::File.open(@path, !File.exist?(@path)))
|
57
57
|
env = Sablon::Environment.new(self, context)
|
58
58
|
env.section_properties = properties
|
59
59
|
#
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Sablon
|
2
|
+
module Test
|
3
|
+
module Assertions
|
4
|
+
def assert_docx_equal(expected_path, actual_path)
|
5
|
+
#
|
6
|
+
# Parse document archives and generate a diff
|
7
|
+
xml_diffs = diff_docx_files(expected_path, actual_path)
|
8
|
+
#
|
9
|
+
# build error message
|
10
|
+
msg = 'The generated document does not match the sample. Please investigate file(s): '
|
11
|
+
msg += xml_diffs.keys.sort.join(', ')
|
12
|
+
xml_diffs.each do |name, diff_text|
|
13
|
+
msg += "\n#{'-' * 72}\nFile: #{name}\n#{diff_text}\n"
|
14
|
+
end
|
15
|
+
msg += '-' * 72 + "\n"
|
16
|
+
msg += "If the generated document is correct, the sample needs to be updated:\n"
|
17
|
+
msg += "\t cp #{actual_path} #{expected_path}"
|
18
|
+
#
|
19
|
+
raise Minitest::Assertion, msg unless xml_diffs.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
# Returns a hash of all XML files that differ in the docx file. This
|
24
|
+
# only checks files that have the extension ".xml" or ".rels".
|
25
|
+
def diff_docx_files(expected_path, actual_path)
|
26
|
+
expected = parse_docx(expected_path)
|
27
|
+
actual = parse_docx(actual_path)
|
28
|
+
xml_diffs = {}
|
29
|
+
#
|
30
|
+
expected.each do |entry_name, expect|
|
31
|
+
next unless entry_name =~ /.xml$|.rels$/
|
32
|
+
next unless expect != actual[entry_name]
|
33
|
+
#
|
34
|
+
xml_diffs[entry_name] = diff(expect, actual[entry_name])
|
35
|
+
end
|
36
|
+
#
|
37
|
+
xml_diffs
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def parse_docx(path)
|
43
|
+
contents = {}
|
44
|
+
#
|
45
|
+
# step over all entries adding them to the hash to diff against
|
46
|
+
Zip::File.open(path).each do |entry|
|
47
|
+
next unless entry.file?
|
48
|
+
content = entry.get_input_stream.read
|
49
|
+
# normalize xml content
|
50
|
+
if entry.name =~ /.xml$|.rels$/
|
51
|
+
content = Nokogiri::XML(content).to_xml(indent: 2)
|
52
|
+
end
|
53
|
+
contents[entry.name] = content
|
54
|
+
end
|
55
|
+
#
|
56
|
+
contents
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/sablon/version.rb
CHANGED
data/misc/TEMPLATE.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
-
|
1
|
+
## Creating a Simple Template
|
2
|
+
|
2
3
|
Creating a template is as easy as creating a normal Word document (`.docx`). Yet it could be confusing to people who haven't used the [Mail Merge](https://support.office.com/en-us/article/Use-mail-merge-to-send-bulk-email-messages-0f123521-20ce-4aa8-8b62-ac211dedefa4) feature in Microsoft Word. The steps are as follows:
|
3
4
|
|
5
|
+
### Setup
|
4
6
|
- Create a new word document
|
5
7
|
|
6
8
|
![Step 1](/misc/step_1.png)
|
@@ -11,6 +13,22 @@ Creating a template is as easy as creating a normal Word document (`.docx`). Yet
|
|
11
13
|
|
12
14
|
- Add mail merge fields
|
13
15
|
|
16
|
+
See [How to add a mail merge field](#how-to-add-a-mail-merge-field) for specific instructions for your operating system.
|
17
|
+
|
18
|
+
- You should then have something like this:
|
19
|
+
|
20
|
+
![Step 6](/misc/step_6.png)
|
21
|
+
|
22
|
+
- A complete template might look like this:
|
23
|
+
|
24
|
+
![Step 7](/misc/step_7.png)
|
25
|
+
|
26
|
+
NOTE: When adding variables, those that display a value are preceded with an equals sign `=`. Those that just perform logics, such as loops and conditionals, do not need a preceding equals sign.
|
27
|
+
|
28
|
+
### How to add a mail merge field
|
29
|
+
|
30
|
+
#### Microsoft Windows
|
31
|
+
|
14
32
|
- Click the `Insert` tab on the ribbon
|
15
33
|
|
16
34
|
![Step 3.1](/misc/step_3_1.png)
|
@@ -33,12 +51,10 @@ Creating a template is as easy as creating a normal Word document (`.docx`). Yet
|
|
33
51
|
|
34
52
|
![Step 5](/misc/step_5.png)
|
35
53
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
NOTE: When adding variables, those that display a value are preceded with an equals sign `=`. Those that just perform logics, such as loops and conditionals, do not need a preceding equals sign.
|
54
|
+
#### MacOS
|
55
|
+
- From the menu bar, open the **Insert** menu and select **Field...**
|
56
|
+
- Under *Categories*, select **Mail Merge**
|
57
|
+
- Under *Field names*, select **MergeField**
|
58
|
+
- Add your variable name in the input box; make sure to leave a space after the word `MERGEFIELD`
|
59
|
+
- Example: `MERGEFIELD =person.first_name`
|
60
|
+
- Click **OK**
|
data/sablon.gemspec
CHANGED
@@ -19,11 +19,13 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.
|
23
|
-
|
22
|
+
spec.required_ruby_version = '>= 2.2'
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'nokogiri', ">= 1.8.5"
|
25
|
+
spec.add_runtime_dependency 'rubyzip', ">= 1.3.0"
|
24
26
|
|
25
27
|
spec.add_development_dependency "bundler", ">= 1.6"
|
26
|
-
spec.add_development_dependency "rake", "~>
|
28
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
27
29
|
spec.add_development_dependency "minitest", "~> 5.4"
|
28
30
|
spec.add_development_dependency "xml-simple"
|
29
31
|
end
|
data/test/configuration_test.rb
CHANGED
@@ -75,8 +75,9 @@ class ConfigurationHTMLTagTest < Sablon::TestCase
|
|
75
75
|
|
76
76
|
# Exercising more of the logic used to conform args into valid
|
77
77
|
def test_html_tag_full_init
|
78
|
-
args = ['a', 'inline'
|
79
|
-
|
78
|
+
args = ['a', 'inline']
|
79
|
+
kwargs = { ast_class: Sablon::HTMLConverter::Run }
|
80
|
+
tag = Sablon::Configuration::HTMLTag.new(*args, **kwargs)
|
80
81
|
assert_equal :a, tag.name
|
81
82
|
assert_equal :inline, tag.type
|
82
83
|
assert_equal Sablon::HTMLConverter::Run, tag.ast_class
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -39,7 +39,7 @@ class HTMLConverterASTBuilderTest < Sablon::TestCase
|
|
39
39
|
def test_merge_properties
|
40
40
|
@builder = new_builder
|
41
41
|
node = Nokogiri::HTML.fragment('<span style="color: #F00; text-decoration: underline wavy">Test</span>').children[0]
|
42
|
-
tag = Struct.new(:properties).new(rStyle: 'Normal')
|
42
|
+
tag = Struct.new(:properties).new({ rStyle: 'Normal' })
|
43
43
|
# test that properties are merged across all three arguments
|
44
44
|
props = @builder.send(:merge_node_properties, node, tag, 'background-color' => '#00F')
|
45
45
|
assert_equal({ 'background-color' => '#00F', rStyle: 'Normal', 'color' => '#F00', 'text-decoration' => 'underline wavy' }, props)
|
data/test/sablon_test.rb
CHANGED
@@ -105,7 +105,8 @@ class SablonConditionalsTest < Sablon::TestCase
|
|
105
105
|
object: OpenStruct.new(true_method: true, false_method: false),
|
106
106
|
success_content: '✓',
|
107
107
|
fail_content: '✗',
|
108
|
-
content: 'Some Content'
|
108
|
+
content: 'Some Content',
|
109
|
+
block_content: Sablon.content(:html, '<p>HTML paragraph injected</p>')
|
109
110
|
}
|
110
111
|
#
|
111
112
|
template.render_to_file @output_path, context
|
@@ -155,7 +156,7 @@ class SablonImagesTest < Sablon::TestCase
|
|
155
156
|
darth = Sablon.content(:image, @image_fixtures.join('darth_vader.jpg'))
|
156
157
|
#
|
157
158
|
im_data = StringIO.new(IO.binread(@image_fixtures.join('clone.jpg')))
|
158
|
-
trooper = Sablon.content(:image, im_data, filename: 'clone.jpg', properties: {height: '
|
159
|
+
trooper = Sablon.content(:image, im_data, filename: 'clone.jpg', properties: {height: '1cm', width: '4cm'})
|
159
160
|
#
|
160
161
|
# with the following context setup all trooper should be reused and
|
161
162
|
# only a single file added to media. R2D2 should get duplicated in the
|
@@ -186,3 +187,25 @@ class SablonImagesTest < Sablon::TestCase
|
|
186
187
|
assert_equal "Filename: 'clone' has no discernable extension", e.message
|
187
188
|
end
|
188
189
|
end
|
190
|
+
|
191
|
+
class SablonSvgImagesTest < Sablon::TestCase
|
192
|
+
def setup
|
193
|
+
super
|
194
|
+
@base_path = Pathname.new(File.expand_path("../", __FILE__))
|
195
|
+
@template_path = @base_path + "fixtures/svg_images_template.docx"
|
196
|
+
@output_path = @base_path + "sandbox/svg_images.docx"
|
197
|
+
@sample_path = @base_path + "fixtures/svg_images_sample.docx"
|
198
|
+
@image_fixtures = @base_path + "fixtures/images"
|
199
|
+
end
|
200
|
+
|
201
|
+
def test_generate_document_from_template
|
202
|
+
template = Sablon.template @template_path
|
203
|
+
|
204
|
+
context = {
|
205
|
+
svg_sample: Sablon.content(:image, @image_fixtures.join('svg_sample.svg'))
|
206
|
+
}
|
207
|
+
|
208
|
+
template.render_to_file @output_path, context
|
209
|
+
assert_docx_equal @sample_path, @output_path
|
210
|
+
end
|
211
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -8,64 +8,11 @@ require "pathname"
|
|
8
8
|
|
9
9
|
$: << File.expand_path('../../lib', __FILE__)
|
10
10
|
require "sablon"
|
11
|
+
require "sablon/test/assertions"
|
11
12
|
|
12
|
-
|
13
|
-
|
14
|
-
def assert_docx_equal(expected_path, actual_path)
|
15
|
-
#
|
16
|
-
# Parse document archives and generate a diff
|
17
|
-
xml_diffs = diff_docx_files(expected_path, actual_path)
|
18
|
-
#
|
19
|
-
# build error message
|
20
|
-
msg = 'The generated document does not match the sample. Please investigate file(s): '
|
21
|
-
msg += xml_diffs.keys.sort.join(', ')
|
22
|
-
xml_diffs.each do |name, diff_text|
|
23
|
-
msg += "\n#{'-' * 72}\nFile: #{name}\n#{diff_text}\n"
|
24
|
-
end
|
25
|
-
msg += '-' * 72 + "\n"
|
26
|
-
msg += "If the generated document is correct, the sample needs to be updated:\n"
|
27
|
-
msg += "\t cp #{actual_path} #{expected_path}"
|
28
|
-
#
|
29
|
-
raise Minitest::Assertion, msg unless xml_diffs.empty?
|
30
|
-
end
|
31
|
-
|
32
|
-
# Returns a hash of all XML files that differ in the docx file. This
|
33
|
-
# only checks files that have the extension ".xml" or ".rels".
|
34
|
-
def diff_docx_files(expected_path, actual_path)
|
35
|
-
expected = parse_docx(expected_path)
|
36
|
-
actual = parse_docx(actual_path)
|
37
|
-
xml_diffs = {}
|
38
|
-
#
|
39
|
-
expected.each do |entry_name, expect|
|
40
|
-
next unless entry_name =~ /.xml$|.rels$/
|
41
|
-
next unless expect != actual[entry_name]
|
42
|
-
#
|
43
|
-
xml_diffs[entry_name] = diff(expect, actual[entry_name])
|
44
|
-
end
|
45
|
-
#
|
46
|
-
xml_diffs
|
47
|
-
end
|
48
|
-
|
49
|
-
def parse_docx(path)
|
50
|
-
contents = {}
|
51
|
-
#
|
52
|
-
# step over all entries adding them to the hash to diff against
|
53
|
-
Zip::File.open(path).each do |entry|
|
54
|
-
next unless entry.file?
|
55
|
-
content = entry.get_input_stream.read
|
56
|
-
# normalize xml content
|
57
|
-
if entry.name =~ /.xml$|.rels$/
|
58
|
-
content = Nokogiri::XML(content).to_xml(indent: 2)
|
59
|
-
end
|
60
|
-
contents[entry.name] = content
|
61
|
-
end
|
62
|
-
#
|
63
|
-
contents
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
13
|
+
class Sablon::TestCase < Minitest::Test
|
14
|
+
include Sablon::Test::Assertions
|
67
15
|
|
68
|
-
class Sablon::TestCase < MiniTest::Test
|
69
16
|
def teardown
|
70
17
|
super
|
71
18
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sablon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yves Senn
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 1.
|
19
|
+
version: 1.8.5
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 1.
|
26
|
+
version: 1.8.5
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rubyzip
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 1.
|
33
|
+
version: 1.3.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 1.
|
40
|
+
version: 1.3.0
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: bundler
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '13.0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '13.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: minitest
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- lib/sablon/processor/section_properties.rb
|
138
138
|
- lib/sablon/template.rb
|
139
139
|
- lib/sablon/test.rb
|
140
|
+
- lib/sablon/test/assertions.rb
|
140
141
|
- lib/sablon/version.rb
|
141
142
|
- misc/TEMPLATE.md
|
142
143
|
- misc/cv_sample.png
|
@@ -174,6 +175,7 @@ files:
|
|
174
175
|
- test/fixtures/images/clone.jpg
|
175
176
|
- test/fixtures/images/darth_vader.jpg
|
176
177
|
- test/fixtures/images/r2d2.jpg
|
178
|
+
- test/fixtures/images/svg_sample.svg
|
177
179
|
- test/fixtures/images_sample.docx
|
178
180
|
- test/fixtures/images_template.docx
|
179
181
|
- test/fixtures/insertion_template.docx
|
@@ -184,6 +186,8 @@ files:
|
|
184
186
|
- test/fixtures/recipe_context.json
|
185
187
|
- test/fixtures/recipe_sample.docx
|
186
188
|
- test/fixtures/recipe_template.docx
|
189
|
+
- test/fixtures/svg_images_sample.docx
|
190
|
+
- test/fixtures/svg_images_template.docx
|
187
191
|
- test/fixtures/xml/comment.xml
|
188
192
|
- test/fixtures/xml/comment_block_and_comment_as_key.xml
|
189
193
|
- test/fixtures/xml/complex_field.xml
|
@@ -227,7 +231,7 @@ homepage: http://github.com/senny/sablon
|
|
227
231
|
licenses:
|
228
232
|
- MIT
|
229
233
|
metadata: {}
|
230
|
-
post_install_message:
|
234
|
+
post_install_message:
|
231
235
|
rdoc_options: []
|
232
236
|
require_paths:
|
233
237
|
- lib
|
@@ -235,16 +239,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
235
239
|
requirements:
|
236
240
|
- - ">="
|
237
241
|
- !ruby/object:Gem::Version
|
238
|
-
version: '
|
242
|
+
version: '2.2'
|
239
243
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
240
244
|
requirements:
|
241
245
|
- - ">="
|
242
246
|
- !ruby/object:Gem::Version
|
243
247
|
version: '0'
|
244
248
|
requirements: []
|
245
|
-
|
246
|
-
|
247
|
-
signing_key:
|
249
|
+
rubygems_version: 3.3.7
|
250
|
+
signing_key:
|
248
251
|
specification_version: 4
|
249
252
|
summary: docx template processor
|
250
253
|
test_files:
|
@@ -267,6 +270,7 @@ test_files:
|
|
267
270
|
- test/fixtures/images/clone.jpg
|
268
271
|
- test/fixtures/images/darth_vader.jpg
|
269
272
|
- test/fixtures/images/r2d2.jpg
|
273
|
+
- test/fixtures/images/svg_sample.svg
|
270
274
|
- test/fixtures/images_sample.docx
|
271
275
|
- test/fixtures/images_template.docx
|
272
276
|
- test/fixtures/insertion_template.docx
|
@@ -277,6 +281,8 @@ test_files:
|
|
277
281
|
- test/fixtures/recipe_context.json
|
278
282
|
- test/fixtures/recipe_sample.docx
|
279
283
|
- test/fixtures/recipe_template.docx
|
284
|
+
- test/fixtures/svg_images_sample.docx
|
285
|
+
- test/fixtures/svg_images_template.docx
|
280
286
|
- test/fixtures/xml/comment.xml
|
281
287
|
- test/fixtures/xml/comment_block_and_comment_as_key.xml
|
282
288
|
- test/fixtures/xml/complex_field.xml
|