rndr 0.0.2

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 703f888719f6993503d82d3786fc7a3eb5c82952
4
+ data.tar.gz: c0d2b4e7a30c6cf7934f4932ff9d9c5b6a9bde11
5
+ SHA512:
6
+ metadata.gz: cb3c39ca03f967924002b91fa64073524dac34084a1b8f2b76b7105beb4c532a73f71ac3dc2b38509642bc791887233004100f302fb83ed0d16a5fc8b60d382a
7
+ data.tar.gz: b069bf6c60fc6bf2ccc1646387a2d38a75ff325a96173c7445f021c684f630325eba1f21c2f89b4d82742034f587eeddf28ca5794cde95ab01412f7bb2fe2180
@@ -0,0 +1,22 @@
1
+ ._*
2
+ .DS_Store
3
+ .*.sw?
4
+ *~
5
+ *.gem
6
+ *.rbc
7
+ /.config
8
+ /.yardoc
9
+ /_yardoc
10
+ /doc/
11
+ /coverage/
12
+ /InstalledFiles
13
+ /pkg/
14
+ /spec/reports/
15
+ /spec/examples.txt
16
+ /test/templates/*.txt
17
+ /test/tmp/
18
+ /test/version_tmp/
19
+ /tmp/
20
+ Gemfile.lock
21
+ .ruby-version
22
+ .ruby-gemset
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --format documentation
3
+ --require spec_helper
@@ -0,0 +1,14 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.3
3
+
4
+ Metrics/AbcSize:
5
+ Max: 20
6
+
7
+ Metrics/ClassLength:
8
+ Enabled: false
9
+
10
+ Metrics/LineLength:
11
+ Max: 100
12
+
13
+ Style/Documentation:
14
+ Enabled: false
@@ -0,0 +1,12 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.1
4
+ env:
5
+ - CI=true
6
+
7
+ deploy:
8
+ provider: rubygems
9
+ on:
10
+ tags: true
11
+ api_key:
12
+ secure: wJ2eSj/CABOHR/jGrYs2liXkyccpIVdu3jiHqpqWcrM4AnOgLoglrv3kpKriizfr/Wi2u9GwltQzdZ0SJQkKbsjmLVBzH/fzPJKiDtndDpUGthUpYGIr3F+qzvmwWKxnpMw1zbXRq37u1v2OPr0PEIcicmvWzi4eM1BQNVYnRLL7MlaQwCOvP4GcCnneH7NVqxB8oPEMoXBKPIln7+T505yEOEUk1mgvzbu0y/lwJpKGGaLmNSiSSeM0x0uC0EgCdh05r9lOS9RtwuC2h0tbfJqaRuIsL+TRPfaWtlrkuqMcJrsbRNb8p2ZL0oh994bdfl8YegC4DbEs4bbu5NrZIETsKBP24QKpgokVAJW8+mqeb7GXChtqScoMO62wZN/5K65kbUNxm81T9NjgyQ5wQvLrU6vH5uzcasZcxJhfVXer3SXtH1RsenjulIM9kUqCU1a8ICfTerTvhKi4rIXcMe9tYHeytdq9E6Wip+mrL/JJHBjxjUtUpkTNoLxLIASF/JVjtla5fo6hVkaw4mAQO1ACisWGLEFdF56Hg98pJ9RrVtmf8PvZPgBuTQN+jq3+nzjLhK/mRxtcW2JXqwSeinqtBuKQHESdnJnIuAyazYlpZD9Xsh39SjRR2xYARipq+HNwNxt9u2AHWWp8/UWqNJxwY4Usp+fi6Li7KBG3AQ8=
@@ -0,0 +1,2 @@
1
+ --readme README.md
2
+ --markup markdown
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
@@ -0,0 +1,108 @@
1
+ # Rndr
2
+ [![Build Status](https://travis-ci.org/arc-ts/rndr.svg?branch=master)](https://travis-ci.org/arc-ts/rndr)
3
+ [![Coverage Status](https://coveralls.io/repos/github/arc-ts/rndr/badge.svg?branch=master)](https://coveralls.io/github/arc-ts/rndr?branch=master)
4
+
5
+ Rndr is a small Ruby cli gem that provides a method of rendering discovered erb templates. Variables for use in template rendering can be used directly by providing a either a `yaml` or `json` file, or alternatively a directory may be supplied along with the variable merging strategy. Rndr supports both standard hash merges or recursive (default).
6
+
7
+ Paths can be ignored by either creating a `.rndrignore` file within the current working directly, or supplying a path to a desired ignore file.
8
+
9
+
10
+ * [Commands](#commands)
11
+ * [Check](#check)
12
+ * [List](#list)
13
+ * [Render](#render)
14
+ * [Vars](#vars)
15
+
16
+ ## Commands
17
+
18
+ ```
19
+ $ bin/rndr help
20
+ Commands:
21
+ rndr check # Verifies discovered erb templates.
22
+ rndr help [COMMAND] # Describe available commands or one specific command
23
+ rndr list # List discovered templates.
24
+ rndr render # Renders discovered templates.
25
+ rndr vars # Lists Combined Variables.
26
+ rndr version # Prints rndr Version Information.
27
+ ...
28
+ ```
29
+
30
+ ### Check
31
+
32
+ ```
33
+ $ bin/rndr help check
34
+ Usage:
35
+ rndr check
36
+
37
+ Options:
38
+ e, [--extension=EXTENSION] # Extension of templates.
39
+ # Default: erb
40
+ i, [--ignore=IGNORE] # Path to file containing list of files to be ignored.
41
+ # Default: /Users/demo/ruby/rndr/.rndrignore
42
+ m, [--merge], [--no-merge] # Recursively merge variables instead of replacing.
43
+ # Default: true
44
+ t, [--template=TEMPLATE] # Path to erb template or directory.
45
+ # Default: /Users/demo/ruby/rndr/rndr
46
+ V, [--vars=VARS] # Path to var file or directory.
47
+ # Default: /Users/demo/ruby/rndr/vars
48
+
49
+ Verifies discovered erb templates.
50
+ ```
51
+
52
+ ### List
53
+
54
+ ```
55
+ $ bin/rndr help list
56
+ Usage:
57
+ rndr list
58
+
59
+ Options:
60
+ e, [--extension=EXTENSION] # Extension of templates.
61
+ # Default: erb
62
+ i, [--ignore=IGNORE] # Path to file containing list of files to be ignored.
63
+ # Default: /Users/demo/ruby/rndr/.rndrignore
64
+ t, [--template=TEMPLATE] # Path to erb template or directory.
65
+ # Default: /Users/demo/ruby/rndr/rndr
66
+
67
+ List discovered templates.
68
+ ```
69
+
70
+ ### Render
71
+
72
+ ```
73
+ $ bin/rndr help render
74
+ Usage:
75
+ rndr render
76
+
77
+ Options:
78
+ e, [--extension=EXTENSION] # Extension of templates.
79
+ # Default: erb
80
+ i, [--ignore=IGNORE] # Path to file containing list of files to be ignored.
81
+ # Default: /Users/demo/ruby/rndr/.rndrignore
82
+ m, [--merge], [--no-merge] # Recursively merge variables instead of replacing.
83
+ # Default: true
84
+ t, [--template=TEMPLATE] # Path to erb template or directory.
85
+ # Default: /Users/demo/ruby/rndr/rndr
86
+ V, [--vars=VARS] # Path to var file or directory.
87
+ # Default: /Users/demo/ruby/rndr/vars
88
+
89
+ Renders discovered templates.
90
+ ```
91
+
92
+ ### Vars
93
+
94
+ ```
95
+ $ bin/rndr help vars
96
+ Usage:
97
+ rndr vars
98
+
99
+ Options:
100
+ f, [--format=FORMAT] # Output Format [yaml|json]
101
+ # Default: yaml
102
+ m, [--merge], [--no-merge] # Recursively merge variables instead of replacing.
103
+ # Default: true
104
+ V, [--vars=VARS] # Path to var file or directory.
105
+ # Default: /Users/demo/ruby/rndr/vars
106
+
107
+ Lists Combined Variables.
108
+ ```
@@ -0,0 +1,9 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'coveralls/rake/task'
3
+ require 'rspec/core/rake_task'
4
+
5
+ RSpec::Core::RakeTask.new(:spec)
6
+ Coveralls::RakeTask.new
7
+
8
+ task :default => :spec
9
+ task :coveralls => [ :spec, :features, 'coveralls:push' ]
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- encoding: utf-8 -*-
3
+ # frozen_string_literal: true
4
+
5
+ Signal.trap('INT') { exit 1 }
6
+
7
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '../lib')
8
+ require 'rndr'
9
+
10
+ Rndr::CLI.start(ARGV)
@@ -0,0 +1,12 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ # Rndr base module
5
+ # @author Bob Killen <rkillen@umich.edu>
6
+
7
+ module Rndr
8
+ require 'rndr/cli'
9
+ require 'rndr/template'
10
+ require 'rndr/util'
11
+ require 'rndr/version'
12
+ end
@@ -0,0 +1,125 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ require 'thor'
4
+
5
+ module Rndr
6
+ # Parent CLI controls for Rndr.
7
+ # @author Bob Killen <rkillen@umich.edu>
8
+ class CLI < Thor
9
+ desc 'check', 'Verifies discovered erb templates.'
10
+ method_option :extension,
11
+ aliases: :e, type: :string, default: 'erb',
12
+ desc: 'Extension of templates.'
13
+ method_option :ignore,
14
+ aliases: :i, type: :string, default: File.join(Dir.pwd, '.rndrignore'),
15
+ desc: 'Path to file containing list of files to be ignored.'
16
+ method_option :merge,
17
+ aliases: :m, type: :boolean, default: true,
18
+ desc: 'Recursively merge variables instead of replacing.'
19
+ method_option :template,
20
+ aliases: :t, type: :string, default: Dir.pwd,
21
+ desc: 'Path to erb template or directory.'
22
+ method_option :vars,
23
+ aliases: :V, type: :string, default: File.join(Dir.pwd, 'vars'),
24
+ desc: 'Path to var file or directory.'
25
+ def check
26
+ results = Rndr.matches(path: options[:template], ext: options[:extension],
27
+ ignore_path: options[:ignore])
28
+ template_vars = Rndr.read_vars(path: options[:vars], merge: options[:merge])
29
+ results.each do |path|
30
+ template = Template.new(path: path, vars: template_vars)
31
+ print_check_result(path: path, result: template.render?)
32
+ end
33
+ end
34
+
35
+ desc 'list', 'List discovered templates.'
36
+ method_option :extension,
37
+ aliases: :e, type: :string, default: 'erb',
38
+ desc: 'Extension of templates.'
39
+ method_option :ignore,
40
+ aliases: :i, type: :string, default: File.join(Dir.pwd, '.rndrignore'),
41
+ desc: 'Path to file containing list of files to be ignored.'
42
+ method_option :template,
43
+ aliases: :t, type: :string, default: Dir.pwd,
44
+ desc: 'Path to erb template or directory.'
45
+ def list
46
+ results = Rndr.matches(path: options[:template], ext: options[:extension],
47
+ ignore_path: '.rndrignore')
48
+ if results.empty?
49
+ puts 'No matching results.'
50
+ else
51
+ puts results
52
+ end
53
+ end
54
+
55
+ desc 'render', 'Renders discovered templates.'
56
+ method_option :extension,
57
+ aliases: :e, type: :string, default: 'erb',
58
+ desc: 'Extension of templates.'
59
+ method_option :ignore,
60
+ aliases: :i, type: :string, default: File.join(Dir.pwd, '.rndrignore'),
61
+ desc: 'Path to file containing list of files to be ignored.'
62
+ method_option :merge,
63
+ aliases: :m, type: :boolean, default: true,
64
+ desc: 'Recursively merge variables instead of replacing.'
65
+ method_option :template,
66
+ aliases: :t, type: :string, default: Dir.pwd,
67
+ desc: 'Path to erb template or directory.'
68
+ method_option :vars,
69
+ aliases: :V, type: :string, default: File.join(Dir.pwd, 'vars'),
70
+ desc: 'Path to var file or directory.'
71
+ def render
72
+ results = Rndr.matches(path: options[:template], ext: options[:extension],
73
+ ignore_path: '.rndrignore')
74
+ template_vars = Rndr.read_vars(path: options[:vars], merge: options[:merge])
75
+ results.each do |path|
76
+ template = Template.new(path: path, vars: template_vars)
77
+ render_path = path.gsub(/.#{options[:extension]}$/, '')
78
+ template.render(render_path) if template.render?
79
+ print_check_result(path: render_path, result: template.render?)
80
+ end
81
+ end
82
+
83
+ desc 'vars', 'Lists Combined Variables.'
84
+ method_option :format,
85
+ aliases: :f, type: :string, default: 'yaml',
86
+ desc: 'Output Format [yaml|json]'
87
+ method_option :merge,
88
+ aliases: :m, type: :boolean, default: true,
89
+ desc: 'Recursively merge variables instead of replacing.'
90
+ method_option :vars,
91
+ aliases: :V, type: :string, default: File.join(Dir.pwd, 'vars'),
92
+ desc: 'Path to var file or directory.'
93
+ def vars
94
+ result = Rndr.read_vars(path: options[:vars], merge: options[:merge])
95
+ case options[:format].downcase
96
+ when 'json'
97
+ puts result.to_json
98
+ when 'yaml'
99
+ puts result.to_yaml
100
+ else
101
+ puts 'Invalid Format.'
102
+ end
103
+ end
104
+
105
+ desc 'version', 'Prints rndr Version Information.'
106
+ map %w(-v --version) => :version
107
+ def version
108
+ puts "Rndr Version: #{Rndr::VERSION}"
109
+ end
110
+
111
+ private
112
+
113
+ # print_check_result puts the results of an attempted Template.render? action.
114
+ # @param path [String] Path to template or rendered template.
115
+ # @param result [Boolean] True is successfully rendered template.
116
+ def print_check_result(path:, result:)
117
+ case result
118
+ when true
119
+ puts "#{path} [OK]"
120
+ when false
121
+ puts "#{path} [FAIL]"
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,48 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ require 'erb'
4
+
5
+ module Rndr
6
+ # This class is used to handle the rendering of `ERB` templates.
7
+ # @author Bob Killen <rkillen@umich.edu>
8
+ class Template
9
+ # Constructs a new instance of Template.
10
+ # @param path [String] The path to the template file.
11
+ # @param vars [Hash] A hash of the variables to be passed to the template's binding.
12
+ def initialize(path:, vars: {})
13
+ @path = File.absolute_path(path)
14
+ @vars = vars
15
+ end
16
+
17
+ # Verifies if a template is renderable or not.
18
+ # @return [Boolean] True if template is renderable.
19
+ def render?
20
+ render_helper
21
+ end
22
+
23
+ # Renders the template to the supplied path.
24
+ # @param render_path [String] Path to desired rendered template location.
25
+ # @return [Boolean] True if template was rendered successfully.
26
+ def render(render_path)
27
+ render_helper(render_path)
28
+ end
29
+
30
+ private
31
+
32
+ # Does the heavy lifting of template generation.
33
+ # If no path is supplied, it simply tests if the template is renderable.
34
+ # @param render_path [String] Path to desired rendered template location.
35
+ # @return [Boolean] True if template is renderable, and rendered file written.
36
+ def render_helper(render_path = nil)
37
+ b = binding
38
+ @vars.each { |k, v| b.local_variable_set(k, v) }
39
+ rendered = ERB.new(File.read(@path)).result(b)
40
+ unless render_path.nil?
41
+ File.open(render_path, 'w') { |f| f.write(rendered) }
42
+ end
43
+ true
44
+ rescue
45
+ false
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,147 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ require 'deep_merge'
4
+ require 'json'
5
+ require 'yaml'
6
+
7
+ module Rndr
8
+ # Accepts a path (either file or directory), a file extension, and the name
9
+ # of a file within the working directory that contains a list of file glob
10
+ # patterns to be skipped. It returns an array of filtered matched paths.
11
+ # @param path [String] The path to the template file or directory.
12
+ # @param ext [String] The File name extension to identify template files.
13
+ # @param ignore_path [String] The path to ignore file.
14
+ # @return [Array<String>] list of paths to matching results.
15
+ def self.matches(path:, ext: 'erb', ignore_path: File.join(Dir.pwd, '.rndrignore'))
16
+ matched_paths = match_files(path: File.absolute_path(path), ext: ext)
17
+ ignore_file_path = File.absolute_path(ignore_path)
18
+ if !matched_paths.empty? && File.exist?(ignore_file_path)
19
+ return filter_ignored_paths(path_list: matched_paths, ignore_path: ignore_file_path)
20
+ else
21
+ return matched_paths
22
+ end
23
+ end
24
+
25
+ # Accepts a file or directory and will attempt to parse the discovered file(s) as either json
26
+ # or yaml. It will then be returned as a hash intended for use with seeding the binding used for
27
+ # template rendering in {Template#render}.
28
+ # @param path [String] The path to the vars file or directory. Will process both json and yaml.
29
+ # @param merge [Boolean] True to enable recursive merge of hashes.
30
+ # @return [Hash] A hash containing the processed variables. Will be used to send to the binding
31
+ # of a rendered template. See {Template#render} for more information.
32
+ def self.read_vars(path:, merge: true)
33
+ vars_path = File.absolute_path(path)
34
+ return read_vars_file(vars_path) if File.file?(vars_path)
35
+ return read_vars_dir(path: vars_path, merge: merge) if File.directory?(vars_path)
36
+ {}
37
+ end
38
+
39
+ class << self
40
+ private
41
+
42
+ # @param path [String] Path to file or directory to test match condition.
43
+ # @param ext [String] The extension to use as the match condition.
44
+ # @return [Array<String>] Array of paths to matching files.
45
+ def match_files(path:, ext:)
46
+ return [path] if File.file?(path) && File.fnmatch("*#{ext}", path)
47
+ if File.directory?(path)
48
+ matched_paths = Dir["#{path}/**/*.#{ext}"]
49
+ matched_paths.reject! { |file| File.directory?(file) }
50
+ return matched_paths
51
+ end
52
+ []
53
+ end
54
+
55
+ # filter_ignored_paths removes paths from the supplied list if they match a
56
+ # path within the supplied ignore_path.
57
+ # @param path_list [Array<String>] Array of paths to matching files before prune
58
+ # from ignore_path.
59
+ # @param ignore_path [String] Path to ignore file. Passed to @see #ignore_paths for
60
+ # processing.
61
+ # @return [Array<String>] Pruned list of paths with files matching the glob patterns
62
+ # in ignore_path removed.
63
+ def filter_ignored_paths(path_list:, ignore_path:)
64
+ ignored_paths = ignore_paths(ignore_path)
65
+ path_list.reject do |file|
66
+ ignored_paths.any? do |ignore|
67
+ File.fnmatch(ignore, file, File::FNM_PATHNAME)
68
+ end
69
+ end
70
+ end
71
+
72
+ # ignore_paths returns a list of paths used to filter possible discovered tempaltes
73
+ # that should be ignored.
74
+ # @param ignore_path [String] Path to ignore file.
75
+ # @return [Array<String>] Generated list of paths to be ignored.
76
+ def ignore_paths(ignore_path)
77
+ ignore_list = File.readlines(ignore_path)
78
+ ignore_list.map! { |line| line.chomp.strip }
79
+ ignore_list.reject! { |line| line.empty? || line =~ /^(#|!)/ }
80
+ ignore_list.map! { |line| File.absolute_path(line, File.dirname(ignore_path)) }
81
+ ignore_list
82
+ end
83
+
84
+ # read_vars_file reads the data stored in file as supplied by path. processed_vars
85
+ # json or yaml
86
+ # @param path [String] Path to file with variables to be processed.
87
+ # @return [Hash, nil] Hash of processed data read from var passed var file.
88
+ def read_vars_file(path)
89
+ data = File.read(path)
90
+ return JSON.load(data) if json?(data)
91
+ return YAML.load(data) if yaml?(data)
92
+ nil
93
+ end
94
+
95
+ # read_vars_dir combines all the variables within a supplied directory. It can injest
96
+ # json or yaml.
97
+ # @param path [String] Path to directory containing files to be ingested and vars
98
+ # processed.
99
+ # @param merge [Boolean] True if variables from files should be recursively merged.
100
+ # @return [Hash] Hash of processed variables read from files within the passed.
101
+ def read_vars_dir(path:, merge:)
102
+ processed_vars = {}
103
+ Dir[File.join(path, '*')].each do |file|
104
+ file_vars = read_vars_file(file)
105
+ unless file_vars.nil?
106
+ processed_vars =
107
+ merge_vars(base_hash: processed_vars, hash: file_vars, merge: merge)
108
+ end
109
+ end
110
+ processed_vars
111
+ end
112
+
113
+ # json? tests if the supplied json is parsable or not.
114
+ # @param data [String] String containing read data from file.
115
+ # @return [Boolean] True if data is valid json.
116
+ def json?(data)
117
+ JSON.parse(data)
118
+ true
119
+ rescue
120
+ false
121
+ end
122
+
123
+ # yaml? tests if the supplied yaml is parsable or not.
124
+ # @param data [String] String containing read data from file.
125
+ # @return [Boolean] True if data is valid yaml.
126
+ def yaml?(data)
127
+ YAML.load(data)
128
+ true
129
+ rescue
130
+ false
131
+ end
132
+
133
+ # merge_vars handles merging hashes, either with a recursive merge (default) or with
134
+ # a standard merge, which has a 'replace' effect.
135
+ # @param base_hash [Hash] Original Hash to have values merged into.
136
+ # @param hash [Hash] Secondary hash to be merged into base hash.
137
+ # @param merge [Boolean] True to enable recursive merging of hashes.
138
+ # @return [Hash] The merged hash.
139
+ def merge_vars(base_hash:, hash:, merge: true)
140
+ if base_hash.is_a?(Hash) && hash.is_a?(Hash)
141
+ return base_hash.deep_merge!(hash) if merge == true
142
+ return base_hash.merge!(hash) if merge == false
143
+ end
144
+ {}
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,8 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ module Rndr
5
+ VERSION = File.read(
6
+ File.expand_path('../../../version.txt', __FILE__)
7
+ ).chomp
8
+ end
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'rndr/version'
6
+
7
+ Gem::Specification.new do |gem|
8
+ gem.name = 'rndr'
9
+ gem.version = Rndr::VERSION
10
+ gem.authors = ['Bob Killen']
11
+ gem.homepage = 'https://github.com/arc-ts/rndr'
12
+ gem.email = ['arcts-dev@umich.edu']
13
+ gem.license = 'MIT'
14
+ gem.summary = 'Render Ruby templates quickly and easily.'
15
+ gem.description = 'rndr is a tool that simply renders Ruby erb ' \
16
+ 'templates for use with other applications.'
17
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
18
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
19
+ gem.require_paths = ['lib']
20
+
21
+ gem.required_ruby_version = '>= 2.3'
22
+
23
+ gem.add_dependency 'deep_merge', '>= 1.1.1'
24
+ gem.add_dependency 'thor', '>= 0.19.1'
25
+
26
+ gem.add_development_dependency 'bundler', '>= 1.12.5'
27
+ gem.add_development_dependency 'rake', '>= 11.2.2'
28
+ gem.add_development_dependency 'rspec', '>= 3.5.0'
29
+ gem.add_development_dependency 'coveralls', '>= 0.8.15'
30
+ end
@@ -0,0 +1,172 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+ require 'rndr'
6
+ require_relative 'spec_helper'
7
+
8
+ module Rndr # rubocop:disable Metris/ModuleLength
9
+ RSpec.describe CLI do
10
+ before(:all) { Dir.chdir(File.join(Dir.pwd, 'test')) }
11
+ after(:all) { Dir.chdir('../') }
12
+
13
+ let(:cli) { CLI.new }
14
+
15
+ describe '#check' do
16
+ context 'When the default options are supplied' do
17
+ before do
18
+ cli.options = {
19
+ extension: 'erb', ignore: '.rndrignore',
20
+ merge: true, template: 'templates', vars: 'vars'
21
+ }
22
+ end
23
+ it 'should list the correctly matched results' do
24
+ expect { cli.check }.to output(/rendertest.txt.erb \[OK\]$/).to_stdout
25
+ expect { cli.check }.to_not output(/ignoretest.txt.erb [OK]$/).to_stdout
26
+ end
27
+ end
28
+
29
+ context 'When an alternate exntesion is provided' do
30
+ before do
31
+ cli.options = {
32
+ extension: 'tmplt', ignore: '.rndrignore',
33
+ merge: true, template: 'templates', vars: 'vars'
34
+ }
35
+ end
36
+ it 'should list the correctly matched results' do
37
+ expect { cli.check }.to output(/exttest.txt.tmplt \[OK\]$/).to_stdout
38
+ expect { cli.check }.to_not output(/.erb/).to_stdout
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '#list' do
44
+ context 'When the default options are supplied' do
45
+ before { cli.options = { extension: 'erb', ignore: '.rndrignore', template: 'templates' } }
46
+ it 'should list the correctly matched results' do
47
+ expect { cli.list }.to output(/rendertest.txt.erb$/).to_stdout
48
+ expect { cli.list }.to_not output(/ignoretest.txt.erb/).to_stdout
49
+ end
50
+ end
51
+ context 'When an alternate extension is provided' do
52
+ before do
53
+ cli.options = { extension: 'tmplt', ignore: '.rndrignore', template: 'templates' }
54
+ end
55
+ it 'should list the correctly matched results' do
56
+ expect { cli.list }.to output(/exttest.txt.tmplt$/).to_stdout
57
+ expect { cli.list }.to_not output(/.erb/).to_stdout
58
+ end
59
+ end
60
+ end
61
+
62
+ describe '#render' do
63
+ let(:rendered_file) { File.absolute_path('../test/templates/rendertest.txt') }
64
+ let(:rendered_ext) { File.absolute_path('../test/templates/exttest.txt') }
65
+ let(:rendered_merged) do
66
+ File.join(File.dirname(__FILE__), 'resources/rendered_merged.txt')
67
+ end
68
+ let(:rendered_replaced) do
69
+ File.join(File.dirname(__FILE__), 'resources/rendered_replaced.txt')
70
+ end
71
+ after(:each) do
72
+ File.delete(rendered_file) if File.exist?(rendered_file)
73
+ File.delete(rendered_ext) if File.exist?(rendered_ext)
74
+ end
75
+
76
+ context 'When the defaults are spplied' do
77
+ before do
78
+ cli.options = {
79
+ extension: 'erb', ignore: '.rndrignore',
80
+ merge: true, template: 'templates', vars: 'vars'
81
+ }
82
+ end
83
+ it 'should render items correctly' do
84
+ expect { cli.render }.to output(/rendertest.txt \[OK\]$/).to_stdout
85
+ expect { cli.render }.to_not output(/ignoretest.txt/).to_stdout
86
+ expect(FileUtils.compare_file(rendered_merged, rendered_file)).to be_truthy
87
+ end
88
+ end
89
+
90
+ context ' When the replace merege strategy is specified' do
91
+ before do
92
+ cli.options = {
93
+ extension: 'erb', ignore: '.rndrignore',
94
+ merge: false, template: 'templates', vars: 'vars'
95
+ }
96
+ end
97
+ it 'should render items correctly' do
98
+ expect { cli.render }.to output(/rendertest.txt \[OK\]$/).to_stdout
99
+ expect { cli.render }.to_not output(/ignoretest.txt/).to_stdout
100
+ expect(FileUtils.compare_file(rendered_replaced, rendered_file)).to be_truthy
101
+ end
102
+ end
103
+
104
+ context 'When provided an alternate extension' do
105
+ before do
106
+ cli.options = {
107
+ extension: 'tmplt', ignore: '.rndrignore',
108
+ merge: true, template: 'templates', vars: 'vars'
109
+ }
110
+ end
111
+ it 'should render items correctly' do
112
+ expect { cli.render }.to output(/exttest.txt \[OK\]$/).to_stdout
113
+ expect { cli.render }.to_not output(/rendertest.txt/).to_stdout
114
+ expect(FileUtils.compare_file(rendered_merged, rendered_ext)).to be_truthy
115
+ end
116
+ end
117
+ end
118
+
119
+ describe '#vars' do
120
+ context 'When a directory is supplied.' do
121
+ context 'should serialize and recursively merge variables' do
122
+ before do
123
+ cli.options = { format: 'yaml', merge: true, vars: 'vars' }
124
+ @merged =
125
+ File.read(File.join(File.dirname(__FILE__), 'resources/vars_merged.txt'))
126
+ end
127
+ it 'should perform a deep merge' do
128
+ expect { cli.vars }.to output(@merged).to_stdout
129
+ end
130
+ end
131
+
132
+ context 'should serialize and merge variables with replace behaviour' do
133
+ before do
134
+ cli.options = { format: 'yaml', merge: false, vars: 'vars' }
135
+ @replaced =
136
+ File.read(File.join(File.dirname(__FILE__), 'resources/vars_replaced.txt'))
137
+ end
138
+ it 'should perform a standard merge' do
139
+ expect { cli.vars }.to output(@replaced).to_stdout
140
+ end
141
+ end
142
+ end
143
+
144
+ context 'When a json file is supplied' do
145
+ before do
146
+ cli.options = { format: 'yaml', merge: true, vars: 'vars/a.json' }
147
+ @vars =
148
+ File.read(File.join(File.dirname(__FILE__), 'resources/vars_a.txt'))
149
+ end
150
+ it 'should serialize the data' do
151
+ expect { cli.vars }.to output(@vars).to_stdout
152
+ end
153
+ end
154
+ context 'When a yaml file is supplied' do
155
+ before do
156
+ cli.options = { format: 'yaml', merge: true, vars: 'vars/b.yaml' }
157
+ @vars =
158
+ File.read(File.join(File.dirname(__FILE__), 'resources/vars_b.txt'))
159
+ end
160
+ it 'should serialize the data' do
161
+ expect { cli.vars }.to output(@vars).to_stdout
162
+ end
163
+ end
164
+ end
165
+
166
+ context '#version' do
167
+ it 'should print the version string' do
168
+ expect { cli.version }.to output(/Rndr Version: #{VERSION}$/).to_stdout
169
+ end
170
+ end
171
+ end
172
+ end
@@ -0,0 +1,17 @@
1
+ ---
2
+ child:
3
+ childarray:
4
+ - arraykey1: arrayval1
5
+ - arraykey2: arrayval2
6
+ - arraykey3: arrayval3
7
+ - arraykey4: arrayval4
8
+ childhash:
9
+ childhashkey1: childhashval1
10
+ childhashkey2: childhashval2
11
+ childhashkey3: childhashval3
12
+ childhashkey4: childhashval4
13
+
14
+
15
+ {"boolkey":false,"numkey":2}
16
+
17
+ parent3: mergeval
@@ -0,0 +1,13 @@
1
+ ---
2
+ child:
3
+ childarray:
4
+ - arraykey3: arrayval3
5
+ - arraykey4: arrayval4
6
+ childhash:
7
+ childhashkey3: childhashval3
8
+ childhashkey4: childhashval4
9
+
10
+
11
+ {"boolkey":false,"numkey":2}
12
+
13
+ parent3: mergeval
@@ -0,0 +1,14 @@
1
+ ---
2
+ parent1:
3
+ child:
4
+ childarray:
5
+ - arraykey1: arrayval1
6
+ - arraykey2: arrayval2
7
+ childhash:
8
+ childhashkey1: childhashval1
9
+ childhashkey2: childhashval2
10
+ parent2:
11
+ boolkey: true
12
+ numkey: 1
13
+ parent3:
14
+ mergetest: mergeval
@@ -0,0 +1,12 @@
1
+ ---
2
+ parent1:
3
+ child:
4
+ childarray:
5
+ - arraykey3: arrayval3
6
+ - arraykey4: arrayval4
7
+ childhash:
8
+ childhashkey3: childhashval3
9
+ childhashkey4: childhashval4
10
+ parent2:
11
+ boolkey: false
12
+ numkey: 2
@@ -0,0 +1,18 @@
1
+ ---
2
+ parent1:
3
+ child:
4
+ childarray:
5
+ - arraykey1: arrayval1
6
+ - arraykey2: arrayval2
7
+ - arraykey3: arrayval3
8
+ - arraykey4: arrayval4
9
+ childhash:
10
+ childhashkey1: childhashval1
11
+ childhashkey2: childhashval2
12
+ childhashkey3: childhashval3
13
+ childhashkey4: childhashval4
14
+ parent2:
15
+ boolkey: false
16
+ numkey: 2
17
+ parent3:
18
+ mergetest: mergeval
@@ -0,0 +1,14 @@
1
+ ---
2
+ parent1:
3
+ child:
4
+ childarray:
5
+ - arraykey3: arrayval3
6
+ - arraykey4: arrayval4
7
+ childhash:
8
+ childhashkey3: childhashval3
9
+ childhashkey4: childhashval4
10
+ parent2:
11
+ boolkey: false
12
+ numkey: 2
13
+ parent3:
14
+ mergetest: mergeval
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'rspec'
5
+
6
+ if ENV['CI']
7
+ require 'coveralls'
8
+ Coveralls.wear!
9
+ end
10
+
11
+ RSpec.configure do |config|
12
+ config.expect_with :rspec do |expectations|
13
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
14
+ end
15
+
16
+ config.mock_with :rspec do |mocks|
17
+ mocks.verify_partial_doubles = true
18
+ end
19
+
20
+ config.shared_context_metadata_behavior = :apply_to_host_groups
21
+ config.disable_monkey_patching!
22
+ config.warnings = true
23
+ # config.formatter = 'documentation' unless defined? config.formatter
24
+ end
@@ -0,0 +1,61 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'rndr'
5
+ require 'yaml'
6
+ require_relative 'spec_helper'
7
+
8
+ module Rndr
9
+ RSpec.describe Template do
10
+ before(:all) do
11
+ Dir.chdir(File.join(Dir.pwd, 'test'))
12
+ @success_tmplt = File.absolute_path('templates/rendertest.txt.erb')
13
+ @fail_tmplt = File.absolute_path('templates/failtest.txt.erb')
14
+ @rendered_success = File.absolute_path('templates/rendertest.txt')
15
+ @rendered_fail = File.absolute_path('templates/failtest.txt')
16
+ @compare_success = File.join(File.dirname(__FILE__), 'resources/rendered_merged.txt')
17
+ @vars =
18
+ YAML.load(File.read(File.join(File.dirname(__FILE__), 'resources/vars_merged.txt')))
19
+ end
20
+ after(:all) do
21
+ Dir.chdir('../')
22
+ File.delete(@rendered_success) if File.exist?(@rendered_success)
23
+ File.delete(@rendered_fail) if File.exist?(@rendered_fail)
24
+ end
25
+
26
+ describe '#render?' do
27
+ describe 'When the template is renderable' do
28
+ subject { Template.new(path: @success_tmplt, vars: @vars).render? }
29
+ it { is_expected.to be_truthy }
30
+ end
31
+
32
+ describe 'When the template is not renderable' do
33
+ subject { Template.new(path: @fail_tmplt, vars: @vars).render? }
34
+ it { is_expected.to be_falsey }
35
+ end
36
+ end
37
+
38
+ describe '#render' do
39
+ context 'When the template is renderable' do
40
+ before(:all) { File.delete(@rendered_success) if File.exist?(@rendered_success) }
41
+ subject { Template.new(path: @success_tmplt, vars: @vars).render(@rendered_success) }
42
+ it { is_expected.to be_truthy }
43
+ it 'should render file' do
44
+ expect(File.exist?(@rendered_success)).to be_truthy
45
+ end
46
+ it 'should render contents correctly' do
47
+ expect(FileUtils.compare_file(@rendered_success, @compare_success)).to be_truthy
48
+ end
49
+ end
50
+
51
+ context 'When the template is not renderable' do
52
+ before(:all) { File.delete(@rendered_fail) if File.exist?(@rendered_fail) }
53
+ subject { Template.new(path: @fail_tmplt, vars: @vars).render(@rendered_fail) }
54
+ it { is_expected.to be_falsey }
55
+ it 'should not render file' do
56
+ expect(File.exist?(@rendered_fail)).to be_falsey
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,82 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
4
+ require 'json'
5
+ require 'rndr'
6
+ require 'rspec'
7
+ require 'yaml'
8
+ require_relative 'spec_helper'
9
+
10
+ module Rndr
11
+ RSpec.describe Rndr do
12
+ before(:all) { Dir.chdir(File.join(Dir.pwd, 'test')) }
13
+ after(:all) { Dir.chdir('../') }
14
+
15
+ describe '#matches' do
16
+ context 'When using the defaults' do
17
+ let(:matched) { [File.absolute_path('templates/rendertest.txt.erb')] }
18
+ let(:ignored) do
19
+ [File.absolute_path('templates/ignoretest.txt.erb'),
20
+ File.absolute_path('templates/failtest.txt.erb')]
21
+ end
22
+ subject(:results) { Rndr.matches(path: 'templates') }
23
+ it 'should be an Array of filtered paths with default extension' do
24
+ expect(results).to be_a(Array)
25
+ expect(results).to match_array(matched)
26
+ end
27
+ end
28
+
29
+ context 'When using an alternate extension' do
30
+ let(:matched) { [File.absolute_path('templates/exttest.txt.tmplt')] }
31
+ let(:ignored) do
32
+ [File.absolute_path('templates/ignoretest.txt.erb'),
33
+ File.absolute_path('templates/failtest.txt.erb')]
34
+ end
35
+ subject(:results) { Rndr.matches(path: 'templates', ext: 'tmplt') }
36
+ it 'should be an Array of paths with alternate extension' do
37
+ expect(results).to be_a(Array)
38
+ expect(results).to match_array(matched)
39
+ end
40
+ end
41
+ end
42
+
43
+ describe '#read_vars' do
44
+ context 'When a directory is supplied' do
45
+ context 'should serialize and recursively merges variables' do
46
+ let(:results) do
47
+ YAML.load(File.read(File.join(File.dirname(__FILE__), 'resources/vars_merged.txt')))
48
+ end
49
+ subject(:vars) { Rndr.read_vars(path: 'vars', merge: true) }
50
+ it 'should perform a deep merge' do
51
+ expect(vars).to eql(results)
52
+ end
53
+ end
54
+ context 'should serialize and merge variables with replace behaviour' do
55
+ let(:results) do
56
+ YAML.load(File.read(File.join(File.dirname(__FILE__), 'resources/vars_replaced.txt')))
57
+ end
58
+ subject(:vars) { Rndr.read_vars(path: 'vars', merge: false) }
59
+ it 'should perform a standard merge' do
60
+ expect(vars).to eql(results)
61
+ end
62
+ end
63
+ end
64
+
65
+ context 'When a json file is supplied' do
66
+ let(:results) { JSON.load(File.read('vars/a.json')) }
67
+ subject(:vars) { Rndr.read_vars(path: 'vars/a.json', merge: true) }
68
+ it 'should serialize the data' do
69
+ expect(vars).to eql(results)
70
+ end
71
+ end
72
+
73
+ context 'When a yaml file is supplied' do
74
+ let(:results) { YAML.load(File.read('vars/b.yaml')) }
75
+ subject(:vars) { Rndr.read_vars(path: 'vars/b.yaml', merge: true) }
76
+ it 'should serialize the data' do
77
+ expect(vars).to eql(results)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,3 @@
1
+ #i r ignored
2
+ templates/ignoretest.txt.erb
3
+ templates/failtest.txt.erb
@@ -0,0 +1,5 @@
1
+ <%= parent1.to_yaml %>
2
+
3
+ <%= parent2.to_json %>
4
+
5
+ parent3: <%= parent3['mergetest'] %>
@@ -0,0 +1,5 @@
1
+ <%= nope.to_yaml %>
2
+
3
+ <%= nope2.to_json %>
4
+
5
+ parent3: <%= nope['itall'] %>
File without changes
@@ -0,0 +1,5 @@
1
+ <%= parent1.to_yaml %>
2
+
3
+ <%= parent2.to_json %>
4
+
5
+ parent3: <%= parent3['mergetest'] %>
@@ -0,0 +1,22 @@
1
+ {
2
+ "parent1": {
3
+ "child": {
4
+ "childarray": [{
5
+ "arraykey1": "arrayval1"
6
+ }, {
7
+ "arraykey2": "arrayval2"
8
+ }],
9
+ "childhash": {
10
+ "childhashkey1": "childhashval1",
11
+ "childhashkey2": "childhashval2"
12
+ }
13
+ }
14
+ },
15
+ "parent2": {
16
+ "boolkey": true,
17
+ "numkey": 1
18
+ },
19
+ "parent3": {
20
+ "mergetest": "mergeval"
21
+ }
22
+ }
@@ -0,0 +1,13 @@
1
+ ---
2
+ parent1:
3
+ child:
4
+ childarray:
5
+ - arraykey3: arrayval3
6
+ - arraykey4: arrayval4
7
+ childhash:
8
+ childhashkey3: childhashval3
9
+ childhashkey4: childhashval4
10
+ parent2:
11
+ boolkey: false
12
+ numkey: 2
13
+
@@ -0,0 +1 @@
1
+ 0.0.2
metadata ADDED
@@ -0,0 +1,163 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rndr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Bob Killen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: deep_merge
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: thor
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.19.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 0.19.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 1.12.5
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.12.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 11.2.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 11.2.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: 3.5.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 3.5.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: coveralls
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 0.8.15
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 0.8.15
97
+ description: rndr is a tool that simply renders Ruby erb templates for use with other
98
+ applications.
99
+ email:
100
+ - arcts-dev@umich.edu
101
+ executables:
102
+ - rndr
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rspec"
108
+ - ".rubocop.yml"
109
+ - ".travis.yml"
110
+ - ".yardopts"
111
+ - Gemfile
112
+ - README.md
113
+ - Rakefile
114
+ - bin/rndr
115
+ - lib/rndr.rb
116
+ - lib/rndr/cli.rb
117
+ - lib/rndr/template.rb
118
+ - lib/rndr/util.rb
119
+ - lib/rndr/version.rb
120
+ - rndr.gemspec
121
+ - spec/cli_spec.rb
122
+ - spec/resources/rendered_merged.txt
123
+ - spec/resources/rendered_replaced.txt
124
+ - spec/resources/vars_a.txt
125
+ - spec/resources/vars_b.txt
126
+ - spec/resources/vars_merged.txt
127
+ - spec/resources/vars_replaced.txt
128
+ - spec/spec_helper.rb
129
+ - spec/template_spec.rb
130
+ - spec/util_spec.rb
131
+ - test/.rndrignore
132
+ - test/templates/exttest.txt.tmplt
133
+ - test/templates/failtest.txt.erb
134
+ - test/templates/ignoretest.txt.erb
135
+ - test/templates/rendertest.txt.erb
136
+ - test/vars/a.json
137
+ - test/vars/b.yaml
138
+ - version.txt
139
+ homepage: https://github.com/arc-ts/rndr
140
+ licenses:
141
+ - MIT
142
+ metadata: {}
143
+ post_install_message:
144
+ rdoc_options: []
145
+ require_paths:
146
+ - lib
147
+ required_ruby_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '2.3'
152
+ required_rubygems_version: !ruby/object:Gem::Requirement
153
+ requirements:
154
+ - - ">="
155
+ - !ruby/object:Gem::Version
156
+ version: '0'
157
+ requirements: []
158
+ rubyforge_project:
159
+ rubygems_version: 2.4.5
160
+ signing_key:
161
+ specification_version: 4
162
+ summary: Render Ruby templates quickly and easily.
163
+ test_files: []