sablon 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -2
- data/README.md +36 -5
- data/lib/sablon.rb +0 -3
- data/lib/sablon/configuration/html_tag.rb +1 -1
- data/lib/sablon/content.rb +56 -0
- data/lib/sablon/context.rb +2 -0
- data/lib/sablon/document_object_model/content_types.rb +35 -0
- data/lib/sablon/document_object_model/file_handler.rb +26 -0
- data/lib/sablon/document_object_model/model.rb +94 -0
- data/lib/sablon/document_object_model/numbering.rb +94 -0
- data/lib/sablon/document_object_model/relationships.rb +111 -0
- data/lib/sablon/environment.rb +13 -16
- data/lib/sablon/html/ast.rb +14 -13
- data/lib/sablon/html/ast_builder.rb +18 -5
- data/lib/sablon/html/node_properties.rb +3 -3
- data/lib/sablon/operations.rb +59 -0
- data/lib/sablon/processor/document.rb +48 -11
- data/lib/sablon/processor/section_properties.rb +11 -4
- data/lib/sablon/template.rb +88 -47
- data/lib/sablon/version.rb +1 -1
- data/misc/image-example.png +0 -0
- data/test/configuration_test.rb +22 -22
- data/test/content_test.rb +50 -0
- data/test/context_test.rb +37 -1
- data/test/environment_test.rb +4 -1
- data/test/executable_test.rb +0 -2
- data/test/fixtures/cv_sample.docx +0 -0
- data/test/fixtures/html_sample.docx +0 -0
- data/test/fixtures/images/c3po.jpg +0 -0
- data/test/fixtures/images/clone.jpg +0 -0
- data/test/fixtures/images/darth_vader.jpg +0 -0
- data/test/fixtures/images/r2d2.jpg +0 -0
- data/test/fixtures/images_sample.docx +0 -0
- data/test/fixtures/images_template.docx +0 -0
- data/test/fixtures/loops_sample.docx +0 -0
- data/test/fixtures/loops_template.docx +0 -0
- data/test/fixtures/recipe_sample.docx +0 -0
- data/test/fixtures/xml/image.xml +91 -0
- data/test/fixtures/xml/loop_with_unique_ids.xml +152 -0
- data/test/fixtures/xml/mock_document/word/document.xml +12 -0
- data/test/html/ast_test.rb +10 -5
- data/test/html/converter_style_test.rb +9 -9
- data/test/html/converter_test.rb +66 -81
- data/test/html/node_properties_test.rb +2 -2
- data/test/html_test.rb +2 -6
- data/test/processor/document_test.rb +80 -3
- data/test/processor/section_properties_test.rb +68 -0
- data/test/sablon_test.rb +77 -5
- data/test/test_helper.rb +109 -9
- metadata +33 -9
- data/lib/sablon/numbering.rb +0 -23
- data/lib/sablon/processor/numbering.rb +0 -47
- data/lib/sablon/relationship.rb +0 -47
- data/lib/sablon/test/assertions.rb +0 -22
- data/test/section_properties_test.rb +0 -41
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.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yves Senn
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|
@@ -117,26 +117,28 @@ files:
|
|
117
117
|
- lib/sablon/configuration/html_tag.rb
|
118
118
|
- lib/sablon/content.rb
|
119
119
|
- lib/sablon/context.rb
|
120
|
+
- lib/sablon/document_object_model/content_types.rb
|
121
|
+
- lib/sablon/document_object_model/file_handler.rb
|
122
|
+
- lib/sablon/document_object_model/model.rb
|
123
|
+
- lib/sablon/document_object_model/numbering.rb
|
124
|
+
- lib/sablon/document_object_model/relationships.rb
|
120
125
|
- lib/sablon/environment.rb
|
121
126
|
- lib/sablon/html/ast.rb
|
122
127
|
- lib/sablon/html/ast_builder.rb
|
123
128
|
- lib/sablon/html/converter.rb
|
124
129
|
- lib/sablon/html/node_properties.rb
|
125
130
|
- lib/sablon/html/visitor.rb
|
126
|
-
- lib/sablon/numbering.rb
|
127
131
|
- lib/sablon/operations.rb
|
128
132
|
- lib/sablon/parser/mail_merge.rb
|
129
133
|
- lib/sablon/processor/document.rb
|
130
|
-
- lib/sablon/processor/numbering.rb
|
131
134
|
- lib/sablon/processor/section_properties.rb
|
132
|
-
- lib/sablon/relationship.rb
|
133
135
|
- lib/sablon/template.rb
|
134
136
|
- lib/sablon/test.rb
|
135
|
-
- lib/sablon/test/assertions.rb
|
136
137
|
- lib/sablon/version.rb
|
137
138
|
- misc/TEMPLATE.md
|
138
139
|
- misc/cv_sample.png
|
139
140
|
- misc/cv_template.png
|
141
|
+
- misc/image-example.png
|
140
142
|
- misc/recipe_sample.png
|
141
143
|
- misc/recipe_template.png
|
142
144
|
- misc/step_1.png
|
@@ -162,8 +164,16 @@ files:
|
|
162
164
|
- test/fixtures/cv_template.docx
|
163
165
|
- test/fixtures/html/html_test_content.html
|
164
166
|
- test/fixtures/html_sample.docx
|
167
|
+
- test/fixtures/images/c3po.jpg
|
168
|
+
- test/fixtures/images/clone.jpg
|
169
|
+
- test/fixtures/images/darth_vader.jpg
|
170
|
+
- test/fixtures/images/r2d2.jpg
|
171
|
+
- test/fixtures/images_sample.docx
|
172
|
+
- test/fixtures/images_template.docx
|
165
173
|
- test/fixtures/insertion_template.docx
|
166
174
|
- test/fixtures/insertion_template_no_styles.docx
|
175
|
+
- test/fixtures/loops_sample.docx
|
176
|
+
- test/fixtures/loops_template.docx
|
167
177
|
- test/fixtures/markdown_sample.docx
|
168
178
|
- test/fixtures/recipe_context.json
|
169
179
|
- test/fixtures/recipe_sample.docx
|
@@ -178,7 +188,10 @@ files:
|
|
178
188
|
- test/fixtures/xml/conditional_without_ending.xml
|
179
189
|
- test/fixtures/xml/corrupt_table.xml
|
180
190
|
- test/fixtures/xml/edited_complex_field.xml
|
191
|
+
- test/fixtures/xml/image.xml
|
192
|
+
- test/fixtures/xml/loop_with_unique_ids.xml
|
181
193
|
- test/fixtures/xml/loop_without_ending.xml
|
194
|
+
- test/fixtures/xml/mock_document/word/document.xml
|
182
195
|
- test/fixtures/xml/paragraph_loop.xml
|
183
196
|
- test/fixtures/xml/paragraph_loop_within_table_cell.xml
|
184
197
|
- test/fixtures/xml/simple_field.xml
|
@@ -195,9 +208,9 @@ files:
|
|
195
208
|
- test/html_test.rb
|
196
209
|
- test/mail_merge_parser_test.rb
|
197
210
|
- test/processor/document_test.rb
|
211
|
+
- test/processor/section_properties_test.rb
|
198
212
|
- test/sablon_test.rb
|
199
213
|
- test/sandbox/.gitkeep
|
200
|
-
- test/section_properties_test.rb
|
201
214
|
- test/support/document_xml_helper.rb
|
202
215
|
- test/support/html_snippets.rb
|
203
216
|
- test/support/xml_snippets.rb
|
@@ -222,7 +235,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
222
235
|
version: '0'
|
223
236
|
requirements: []
|
224
237
|
rubyforge_project:
|
225
|
-
rubygems_version: 2.
|
238
|
+
rubygems_version: 2.6.8
|
226
239
|
signing_key:
|
227
240
|
specification_version: 4
|
228
241
|
summary: docx template processor
|
@@ -239,8 +252,16 @@ test_files:
|
|
239
252
|
- test/fixtures/cv_template.docx
|
240
253
|
- test/fixtures/html/html_test_content.html
|
241
254
|
- test/fixtures/html_sample.docx
|
255
|
+
- test/fixtures/images/c3po.jpg
|
256
|
+
- test/fixtures/images/clone.jpg
|
257
|
+
- test/fixtures/images/darth_vader.jpg
|
258
|
+
- test/fixtures/images/r2d2.jpg
|
259
|
+
- test/fixtures/images_sample.docx
|
260
|
+
- test/fixtures/images_template.docx
|
242
261
|
- test/fixtures/insertion_template.docx
|
243
262
|
- test/fixtures/insertion_template_no_styles.docx
|
263
|
+
- test/fixtures/loops_sample.docx
|
264
|
+
- test/fixtures/loops_template.docx
|
244
265
|
- test/fixtures/markdown_sample.docx
|
245
266
|
- test/fixtures/recipe_context.json
|
246
267
|
- test/fixtures/recipe_sample.docx
|
@@ -255,7 +276,10 @@ test_files:
|
|
255
276
|
- test/fixtures/xml/conditional_without_ending.xml
|
256
277
|
- test/fixtures/xml/corrupt_table.xml
|
257
278
|
- test/fixtures/xml/edited_complex_field.xml
|
279
|
+
- test/fixtures/xml/image.xml
|
280
|
+
- test/fixtures/xml/loop_with_unique_ids.xml
|
258
281
|
- test/fixtures/xml/loop_without_ending.xml
|
282
|
+
- test/fixtures/xml/mock_document/word/document.xml
|
259
283
|
- test/fixtures/xml/paragraph_loop.xml
|
260
284
|
- test/fixtures/xml/paragraph_loop_within_table_cell.xml
|
261
285
|
- test/fixtures/xml/simple_field.xml
|
@@ -272,9 +296,9 @@ test_files:
|
|
272
296
|
- test/html_test.rb
|
273
297
|
- test/mail_merge_parser_test.rb
|
274
298
|
- test/processor/document_test.rb
|
299
|
+
- test/processor/section_properties_test.rb
|
275
300
|
- test/sablon_test.rb
|
276
301
|
- test/sandbox/.gitkeep
|
277
|
-
- test/section_properties_test.rb
|
278
302
|
- test/support/document_xml_helper.rb
|
279
303
|
- test/support/html_snippets.rb
|
280
304
|
- test/support/xml_snippets.rb
|
data/lib/sablon/numbering.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
module Sablon
|
2
|
-
class Numbering
|
3
|
-
attr_reader :definitions
|
4
|
-
|
5
|
-
Definition = Struct.new(:numid, :style) do
|
6
|
-
def inspect
|
7
|
-
"#<Numbering #{numid}:#{style}"
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@numid = 1000
|
13
|
-
@definitions = []
|
14
|
-
end
|
15
|
-
|
16
|
-
def register(style)
|
17
|
-
@numid += 1
|
18
|
-
definition = Definition.new(@numid, style)
|
19
|
-
@definitions << definition
|
20
|
-
definition
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
module Sablon
|
2
|
-
module Processor
|
3
|
-
class Numbering
|
4
|
-
LIST_DEFINITION = <<-XML.gsub(/^\s+/, '').tr("\n", '')
|
5
|
-
<w:num w:numId="%s">
|
6
|
-
<w:abstractNumId w:val="%s" />
|
7
|
-
</w:num>
|
8
|
-
XML
|
9
|
-
|
10
|
-
def self.process(doc, env)
|
11
|
-
processor = new(doc)
|
12
|
-
processor.manipulate env
|
13
|
-
doc
|
14
|
-
end
|
15
|
-
|
16
|
-
def initialize(doc)
|
17
|
-
@doc = doc
|
18
|
-
end
|
19
|
-
|
20
|
-
def manipulate(env)
|
21
|
-
env.numbering.definitions.each do |definition|
|
22
|
-
abstract_num_ref = find_definition(definition.style)
|
23
|
-
abstract_num_copy = abstract_num_ref.dup
|
24
|
-
abstract_num_copy['w:abstractNumId'] = definition.numid
|
25
|
-
abstract_num_copy.xpath('./w:nsid').each(&:remove)
|
26
|
-
container.prepend_child abstract_num_copy
|
27
|
-
container.add_child(LIST_DEFINITION % [definition.numid, abstract_num_copy['w:abstractNumId']])
|
28
|
-
end
|
29
|
-
@doc
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
def container
|
34
|
-
@container ||= @doc.xpath('//w:numbering').first
|
35
|
-
end
|
36
|
-
|
37
|
-
def find_definition(style)
|
38
|
-
abstract_num = @doc.xpath("//w:abstractNum[descendant-or-self::*[w:pStyle[@w:val='#{style}']]]").first
|
39
|
-
if abstract_num
|
40
|
-
abstract_num
|
41
|
-
else
|
42
|
-
raise ArgumentError, "Could not find w:abstractNum definition for style: #{style.inspect}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
data/lib/sablon/relationship.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Sablon
|
2
|
-
# Handles storing referenced relationships in the document.xml file and
|
3
|
-
# writing them to the document.xml.rels file
|
4
|
-
class Relationship
|
5
|
-
attr_accessor :relationships
|
6
|
-
|
7
|
-
def initialize
|
8
|
-
@relationships = []
|
9
|
-
end
|
10
|
-
|
11
|
-
def add_found_relationships(content, output_stream)
|
12
|
-
output_stream.put_next_entry('word/_rels/document.xml.rels')
|
13
|
-
#
|
14
|
-
unless @relationships.empty?
|
15
|
-
rels_doc = Nokogiri::XML(content)
|
16
|
-
rels_doc_root = rels_doc.root
|
17
|
-
# convert new rels to nodes
|
18
|
-
node_set = convert_relationships_to_node_set(rels_doc)
|
19
|
-
@relationships = []
|
20
|
-
# add new nodes to XML content
|
21
|
-
rels_doc_root.last_element_child.after(node_set)
|
22
|
-
content = rels_doc.to_xml(indent: 0, save_with: 0)
|
23
|
-
end
|
24
|
-
#
|
25
|
-
output_stream.write(content)
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
# Builds a set of Relationship XML nodes from the stored relationships
|
31
|
-
def convert_relationships_to_node_set(doc)
|
32
|
-
node_set = Nokogiri::XML::NodeSet.new(doc)
|
33
|
-
@relationships.each do |relationship|
|
34
|
-
rel_tag = "<Relationship#{relationship_attributes(relationship)}/>"
|
35
|
-
node_set << Nokogiri::XML.fragment(rel_tag).children.first
|
36
|
-
end
|
37
|
-
#
|
38
|
-
node_set
|
39
|
-
end
|
40
|
-
|
41
|
-
# Builds the attribute string for the relationship XML node
|
42
|
-
def relationship_attributes(relationship)
|
43
|
-
return '' if relationship.nil? || relationship.empty?
|
44
|
-
' ' + relationship.map { |k, v| %(#{k}="#{v}") }.join(' ')
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
module Sablon
|
2
|
-
module Test
|
3
|
-
module Assertions
|
4
|
-
def assert_docx_equal(expected_path, actual_path)
|
5
|
-
if get_document_xml(expected_path) != get_document_xml(actual_path)
|
6
|
-
msg = <<-error
|
7
|
-
The generated document does not match the sample. Please investigate.
|
8
|
-
|
9
|
-
If the generated document is correct, the sample needs to be updated:
|
10
|
-
\t cp #{actual_path} #{expected_path}
|
11
|
-
error
|
12
|
-
fail msg
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def get_document_xml(path)
|
17
|
-
document_xml_entry = Zip::File.open(path).get_entry("word/document.xml")
|
18
|
-
document_xml_entry.get_input_stream.read
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
@@ -1,41 +0,0 @@
|
|
1
|
-
require "test_helper"
|
2
|
-
require "support/document_xml_helper"
|
3
|
-
|
4
|
-
class SectionPropertiesTest < Sablon::TestCase
|
5
|
-
include DocumentXMLHelper
|
6
|
-
|
7
|
-
def test_assign_start_page_number_with_pgNumType_tag
|
8
|
-
xml = wrap <<-documentxml
|
9
|
-
<w:body>
|
10
|
-
<w:sectPr w:rsidR="00FC1AFD" w:rsidSect="006745DF">
|
11
|
-
<w:pgSz w:w="11900" w:h="16840"/>
|
12
|
-
<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="708" w:footer="708" w:gutter="0"/>
|
13
|
-
<w:pgNumType w:start="1"/>
|
14
|
-
<w:cols w:space="708"/>
|
15
|
-
<w:docGrid w:linePitch="360"/>
|
16
|
-
</w:sectPr>
|
17
|
-
</w:body>
|
18
|
-
documentxml
|
19
|
-
properties = Sablon::Processor::SectionProperties.from_document(xml)
|
20
|
-
assert_equal "1", properties.start_page_number
|
21
|
-
properties.start_page_number = "23"
|
22
|
-
assert_equal "23", properties.start_page_number
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_assign_start_page_number_without_pgNumType_tag
|
26
|
-
xml = wrap <<-documentxml
|
27
|
-
<w:body>
|
28
|
-
<w:sectPr w:rsidR="00FC1AFD" w:rsidSect="006745DF">
|
29
|
-
<w:pgSz w:w="11900" w:h="16840"/>
|
30
|
-
<w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="708" w:footer="708" w:gutter="0"/>
|
31
|
-
<w:cols w:space="708"/>
|
32
|
-
<w:docGrid w:linePitch="360"/>
|
33
|
-
</w:sectPr>
|
34
|
-
</w:body>
|
35
|
-
documentxml
|
36
|
-
properties = Sablon::Processor::SectionProperties.from_document(xml)
|
37
|
-
assert_nil properties.start_page_number
|
38
|
-
properties.start_page_number = "16"
|
39
|
-
assert_equal "16", properties.start_page_number
|
40
|
-
end
|
41
|
-
end
|