openxml_docx_templater 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9e44105a83cceb34f68989e87a812785660a1cb8
4
+ data.tar.gz: 738f88c71f5788ec30ce40e0cad79f1ca50492fa
5
+ SHA512:
6
+ metadata.gz: 4d1b6eee10f00beea595e90ea4785435abb4ab304cdb3c6be0cf11ebbf4716242bcad8dbbe06a2d4c838e5b0dfceb55ba43d6f6a852b776a94b426c2909c889d
7
+ data.tar.gz: bbab5dd250bec7ee756aeee9c63fbe9255892e88cfc32dad3bdfbbe484c79637b5a30095be9bff4efbdab2daca368707cdbd89e98abec1fac6e08ccedc50dbca
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.3
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in openxml_docx_templater.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Andrew Ageev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # OpenxmlDocxTemplater
2
+
3
+ OpenxmlDocxTempleter allows you to embed ruby code in MS Office documents (.docx files). You provide .docx template with ruby code, inside a special markup, and the data. In this way gem generates the document. It must be familiar to you, if you know erb!
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'openxml_docx_templater'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install openxml_docx_templater
20
+
21
+ ## Usage
22
+
23
+ OpenxmlDocxTemplater is the best to demonstrate with an example.
24
+ At the picture shown below, you can see the MS Word template with ruby code (this template, the output file, and the sample script can be found in [examples directory](https://github.com/AgeevAndrew/openxml_docx_templater/tree/master/examples)).
25
+
26
+ ![Template](https://github.com/AgeevAndrew/openxml_docx_templater/tree/master/examples/images/template.PNG?raw=true)
27
+
28
+ This image is a screenshot of example_template.docx from the [examples directory](https://github.com/AgeevAndrew/openxml_docx_templater/tree/master/examples). It is a regular Microsoft Office document with ruby code, embedded inside a special markup. That ruby code drives the document creation. You can use conditions, loops, blocks — in fact, the whole ruby language. And you can apply any MS Office formatting to the outputted variables or static text.
29
+
30
+ The second line in the template is `{%= @title1 %}`. That means output the value of variable `title1`. This variable will be replaced in the generated document, but it will still be bold.
31
+
32
+ You can take that template, provide the data and generate the final document:
33
+
34
+ require 'openxml_docx_templater'
35
+
36
+ class Example
37
+ include OpenxmlDocxTemplater::Generator
38
+
39
+ Brand = Struct.new(:name, :models)
40
+ Model = Struct.new(:name, :description, :cost)
41
+
42
+ def generate
43
+ @is_usa = true
44
+ @title1 = "Price"
45
+ @title2 = "Прайс"
46
+
47
+ lg_models = [Model.new('Google Nexus 5x', 'LG Nexus 5x was released in November 2015.', '$550'),
48
+ Model.new('Google Nexus 5', 'LG Nexus 5 was released in November 2013.', '$350'),
49
+ Model.new('Google Nexus 6p', 'LG nexus 6p was released in November 2015.', '$750'),
50
+ ]
51
+ lg = Brand.new("LG", lg_models)
52
+
53
+ iphone_models = [Model.new('iPhone 6+', 'iPhone 6+ was released in September 2014.', '$1000'),
54
+ Model.new('iPhone 6', 'iPhone 6 was released in September 2014.', '$700')]
55
+ iphone = Brand.new("iPhone", iphone_models)
56
+
57
+ @brands = [lg, iphone]
58
+
59
+ render_msword 'example_template.docx'
60
+ end
61
+ end
62
+
63
+ The key parts are `include OpenxmlDocxTemplater::Generator` and `render_msword`. The data for the template must be provided as instance variables.
64
+
65
+ Following picture shows the generated document. It is a screenshot of the example_template_output.docx document from the [examples directory](https://github.com/AgeevAndrew/openxml_docx_templater/tree/master/examples).
66
+
67
+ ![Document](https://github.com/AgeevAndrew/openxml_docx_templater/tree/master/examples/images/output.PNG?raw=true)
68
+
69
+ ## Contributing
70
+
71
+ 1. Fork it
72
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
73
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
74
+ 4. Push to the branch (`git push origin my-new-feature`)
75
+ 5. Create new Pull Request
76
+
77
+ ## License
78
+
79
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
80
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "openxml_docx_templater"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,33 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), "..", "lib"))
2
+
3
+ require 'openxml_docx_templater'
4
+
5
+ class Example
6
+ include OpenxmlDocxTemplater::Generator
7
+
8
+ Brand = Struct.new(:name, :models)
9
+ Model = Struct.new(:name, :description, :cost)
10
+
11
+ def generate
12
+ @is_usa = true
13
+ @title1 = "Price"
14
+ @title2 = "Прайс"
15
+
16
+ lg_models = [Model.new('Google Nexus 5x', 'LG Nexus 5x was released in November 2015.', '$550'),
17
+ Model.new('Google Nexus 5', 'LG Nexus 5 was released in November 2013.', '$350'),
18
+ Model.new('Google Nexus 6p', 'LG nexus 6p was released in November 2015.', '$750'),
19
+ ]
20
+ lg = Brand.new("LG", lg_models)
21
+
22
+ iphone_models = [Model.new('iPhone 6+', 'iPhone 6+ was released in September 2014.', '$1000'),
23
+ Model.new('iPhone 6', 'iPhone 6 was released in September 2014.', '$700')]
24
+ iphone = Brand.new("iPhone", iphone_models)
25
+
26
+ @brands = [lg, iphone]
27
+
28
+ render_msword 'example_template.docx'
29
+ end
30
+ end
31
+
32
+ example = Example.new
33
+ example.generate
Binary file
Binary file
Binary file
@@ -0,0 +1,13 @@
1
+ require "openxml_docx_templater/version"
2
+ require "openxml_docx_templater/debug"
3
+ require "openxml_docx_templater/node_type"
4
+ require "openxml_docx_templater/escape_xml"
5
+ require "openxml_docx_templater/line"
6
+ require "openxml_docx_templater/xml_reader"
7
+ require "openxml_docx_templater/docx_eruby"
8
+ require "openxml_docx_templater/template"
9
+ require "openxml_docx_templater/generator"
10
+
11
+ module OpenxmlDocxTemplater
12
+ # Your code goes here...
13
+ end
@@ -0,0 +1,19 @@
1
+ module OpenxmlDocxTemplater
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,90 @@
1
+ module OpenxmlDocxTemplater
2
+ class DocxEruby
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
+ elsif indicator == '=' # <%= %>
67
+ src << Line.string(code)
68
+ elsif indicator == '%' # <%% %>
69
+ src << Line.literal(code)
70
+ end
71
+ end
72
+
73
+ rest = pos == 0 ? text : text[pos..-1]
74
+
75
+ src << Line.text(rest) unless rest.nil? or rest.empty?
76
+ src
77
+ end
78
+
79
+ def is_nonpair_tag? tag
80
+ tag =~ /<.+?\/>/
81
+ end
82
+
83
+ def is_matching_pair? open, close
84
+ open = open.to_s.strip
85
+ close = close.to_s.strip
86
+
87
+ close == "</#{open[1, close.length - 3]}>"
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,26 @@
1
+ class String
2
+
3
+ CODE_LINE_PATTERN = /{(.*?)%(.+?)%(.*?)}/
4
+ TAG_PATTERN = /<(.+?)>[\n]?/m
5
+
6
+ def escape_xml
7
+ mgsub!([[/&/, '&amp;'], [/</, '&lt;'], [/>/, '&gt;']])
8
+ end
9
+
10
+ def convert_newlines
11
+ gsub!("\n", '<w:br/>')
12
+ self
13
+ end
14
+
15
+ def refact
16
+ gsub(CODE_LINE_PATTERN) { |result| result.gsub(TAG_PATTERN, "") }
17
+ end
18
+
19
+ def mgsub!(key_value_pairs=[].freeze)
20
+ regexp_fragments = key_value_pairs.collect { |k, v| k }
21
+ gsub!(Regexp.union(*regexp_fragments)) do |match|
22
+ key_value_pairs.detect { |k, v| k =~ match }[1]
23
+ end
24
+ self
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module OpenxmlDocxTemplater
2
+ module Generator
3
+ def render_msword template_path, output_path = output_name(template_path)
4
+ template = Template.new template_path, output_path
5
+ template.process binding
6
+ end
7
+
8
+ private
9
+
10
+ def output_name input
11
+ if input =~ /(.+)\.docx\Z/
12
+ "#{$1}_output.docx"
13
+ else
14
+ "#{input}_output.docx"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,68 @@
1
+ module OpenxmlDocxTemplater
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
+ def self.literal txt
26
+ LiteralLine.new txt
27
+ end
28
+
29
+ end
30
+
31
+ class TextLine < Line
32
+ def to_buf
33
+ " _buf << '" << escape_text(@text) << "';"
34
+ end
35
+
36
+ def escape_text text
37
+ text.gsub(/['\\]/, '\\\\\&')
38
+ end
39
+ end
40
+
41
+ class CodeLine < Line
42
+ def to_buf
43
+ escape_code(@text) << ';'
44
+ end
45
+
46
+ def escape_code code
47
+ code.mgsub! [[/&apos;/, "'"], [/&gt;/, '>'], [/&lt/, '<'], [/&quot;/, '"'], [/&amp;/, '&']]
48
+ end
49
+ end
50
+
51
+ class StringLine < CodeLine
52
+ def to_buf
53
+ " _buf << (" << escape_code(@text) << ").to_s.escape_xml.convert_newlines;"
54
+ end
55
+
56
+ def convert_newlines text
57
+ text.gsub("First line", '<w:br/>')
58
+ end
59
+ end
60
+
61
+ class LiteralLine < CodeLine
62
+ def to_buf
63
+ " _buf << (" << escape_code(@text) << ").to_s;"
64
+ end
65
+ end
66
+
67
+ end
68
+
@@ -0,0 +1,7 @@
1
+ module OpenxmlDocxTemplater
2
+ class NodeType
3
+ TAG = 1
4
+ CONTROL = 2
5
+ TEMPLATE = 3
6
+ end
7
+ end
@@ -0,0 +1,31 @@
1
+ require 'zip'
2
+ require 'fileutils'
3
+
4
+ module OpenxmlDocxTemplater
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
+ tmpfiles = []
15
+ Zip::File.open(@template) do |zipfile|
16
+ %w(word/document.xml word/styles.xml).each do |xml_file|
17
+ content = zipfile.read(xml_file).refact
18
+
19
+ docxeruby = DocxEruby.new(XmlReader.new(content))
20
+ out = docxeruby.evaluate(context)
21
+
22
+ tmpfiles << (file = Tempfile.new("openxml_template"))
23
+ file << out
24
+ file.close
25
+
26
+ zipfile.replace(xml_file, file.path)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module OpenxmlDocxTemplater
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,31 @@
1
+ module OpenxmlDocxTemplater
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
14
+ text = @src[last_match_pos...m.begin(0)]
15
+ yield text, 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,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'openxml_docx_templater/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "openxml_docx_templater"
8
+ spec.version = OpenxmlDocxTemplater::VERSION
9
+ spec.authors = ["Andrew Ageev"]
10
+ spec.email = ["ageev86@gmail.com"]
11
+
12
+ spec.summary = %q{Simple creation .docx files by templates}
13
+ spec.description = %q{Simple creation .docx files by templates}
14
+ spec.homepage = "https://github.com/AgeevAndrew/openxml_docx_templater"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.10"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_dependency 'rubyzip'
25
+
26
+ spec.add_development_dependency "rspec"
27
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: openxml_docx_templater
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Ageev
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.10'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.10'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubyzip
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Simple creation .docx files by templates
70
+ email:
71
+ - ageev86@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".travis.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - bin/console
84
+ - bin/setup
85
+ - examples/example.rb
86
+ - examples/example_template.docx
87
+ - examples/example_template_output.docx
88
+ - examples/images/output.PNG
89
+ - examples/images/template.PNG
90
+ - lib/openxml_docx_templater.rb
91
+ - lib/openxml_docx_templater/debug.rb
92
+ - lib/openxml_docx_templater/docx_eruby.rb
93
+ - lib/openxml_docx_templater/escape_xml.rb
94
+ - lib/openxml_docx_templater/generator.rb
95
+ - lib/openxml_docx_templater/line.rb
96
+ - lib/openxml_docx_templater/node_type.rb
97
+ - lib/openxml_docx_templater/template.rb
98
+ - lib/openxml_docx_templater/version.rb
99
+ - lib/openxml_docx_templater/xml_reader.rb
100
+ - openxml_docx_templater.gemspec
101
+ homepage: https://github.com/AgeevAndrew/openxml_docx_templater
102
+ licenses:
103
+ - MIT
104
+ metadata: {}
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.4.5.1
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Simple creation .docx files by templates
125
+ test_files: []