magma_cli 0.0.8
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.
- checksums.yaml +7 -0
- data/.dockerignore +2 -0
- data/.github/CODE_OF_CONDUCT.md +74 -0
- data/.github/ISSUE_TEMPLATE/BUG_REPORT.md +26 -0
- data/.github/ISSUE_TEMPLATE/FEATURE_REQUEST.md +17 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +53 -0
- data/.ruby-version +1 -0
- data/.travis.yml +14 -0
- data/Dockerfile +36 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +62 -0
- data/LICENSE +504 -0
- data/Makefile +40 -0
- data/README.md +56 -0
- data/Rakefile +20 -0
- data/bin/console +13 -0
- data/bin/dmagma +4 -0
- data/bin/magma +9 -0
- data/bin/setup +8 -0
- data/entrypoint.sh +7 -0
- data/lib/magma/app.rb +73 -0
- data/lib/magma/common.rb +36 -0
- data/lib/magma/config/mlt.rb +90 -0
- data/lib/magma/config.rb +4 -0
- data/lib/magma/preparer.rb +85 -0
- data/lib/magma/renderer.rb +123 -0
- data/lib/magma/templater.rb +78 -0
- data/lib/magma/utils.rb +57 -0
- data/lib/magma/version.rb +3 -0
- data/lib/magma.rb +6 -0
- data/magma.gemspec +30 -0
- metadata +175 -0
data/lib/magma/app.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# rubocop:disable Lint/MissingCopEnableDirective, Metrics/LineLength
|
2
|
+
|
3
|
+
require 'etc'
|
4
|
+
require 'tempfile'
|
5
|
+
require 'thor'
|
6
|
+
require 'magma/preparer'
|
7
|
+
require 'magma/renderer'
|
8
|
+
require 'magma/templater'
|
9
|
+
|
10
|
+
module Magma
|
11
|
+
# The CLI application
|
12
|
+
class App < Thor
|
13
|
+
class << self
|
14
|
+
def exit_on_failure?
|
15
|
+
true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'render [outfile]', 'Renders an MLT into an HLS video'
|
20
|
+
option :context, type: :hash, default: {}, aliases: 'c', desc: 'Render-time context'
|
21
|
+
option :data_file, type: :string, aliases: 'D', desc: 'Static data file, accepts JSON or YML'
|
22
|
+
option :enable_real_time, type: :boolean, default: false, aliases: 'r', desc: 'Render in real-time'
|
23
|
+
option :format, type: :string, default: 'mp4', aliases: 'f', enum: Renderer::SUPPORTED_FORMATS, desc: 'Encoding format'
|
24
|
+
option :globals, type: :hash, default: {}, aliases: 'g', desc: 'Global data overrides'
|
25
|
+
option :infile, type: :string, aliases: 'i', desc: 'Input file', required: true
|
26
|
+
option :length, type: :numeric, default: 2, desc: 'Set the target length in seconds'
|
27
|
+
option :preset, type: :string, default: 'fast', desc: 'Video preset for encoding'
|
28
|
+
option :real_time, type: :numeric, default: Etc.nprocessors, aliases: 'n', desc: 'Number of cores (real-time)'
|
29
|
+
option :size, type: :string, default: '1280x720', aliases: 's', desc: 'Frame size (width x height)'
|
30
|
+
option :skip_template, type: :boolean, default: false, desc: 'Skips template-filling step'
|
31
|
+
option :vcodec, type: :string, desc: 'Video codec to use for encoding'
|
32
|
+
def render(outfile)
|
33
|
+
if options[:skip_template]
|
34
|
+
Renderer.call outfile, options
|
35
|
+
else
|
36
|
+
template = Tempfile.new [File.basename(outfile), '.mlt']
|
37
|
+
|
38
|
+
begin
|
39
|
+
Preparer.call options[:infile], options.merge(outfile: template)
|
40
|
+
Templater.call template, options.merge(outfile: template)
|
41
|
+
Renderer.call outfile, options.merge(infile: template.path)
|
42
|
+
ensure
|
43
|
+
template.close
|
44
|
+
template.unlink
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'template [file]', 'Fills a template'
|
50
|
+
option :context, type: :hash, default: {}, aliases: 'c', desc: 'Render-time context'
|
51
|
+
option :globals, type: :hash, default: {}, aliases: 'g', desc: 'Global data overrides'
|
52
|
+
option :data_file, type: :string, aliases: 'D', desc: 'Static data file, accepts JSON or YML'
|
53
|
+
option :outfile, type: :string, aliases: 'o', desc: 'Output file'
|
54
|
+
option :overwrite, type: :boolean, default: false, aliases: 'O', desc: 'Overwrite input file'
|
55
|
+
option :print, type: :string, aliases: 'p', desc: 'Print output'
|
56
|
+
def template(infile = nil)
|
57
|
+
Templater.call infile, options
|
58
|
+
end
|
59
|
+
|
60
|
+
desc 'prepare [file]', 'Prepares a template'
|
61
|
+
option :outfile, type: :string, aliases: 'o', desc: 'Output file'
|
62
|
+
option :overwrite, type: :boolean, default: false, aliases: 'O', desc: 'Overwrite input file'
|
63
|
+
option :print, type: :string, aliases: 'p', desc: 'Print output'
|
64
|
+
def prepare(infile = nil)
|
65
|
+
Preparer.call infile, options
|
66
|
+
end
|
67
|
+
|
68
|
+
desc 'version', 'Displays the version'
|
69
|
+
def version
|
70
|
+
puts Magma::VERSION
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/magma/common.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module Magma
|
4
|
+
module Common
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
class_methods do
|
8
|
+
def call(*args)
|
9
|
+
new(*args).call
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def handle_output!(output, options)
|
14
|
+
output!(output) if options[:print]
|
15
|
+
overwrite!(options[:infile], output) if options[:overwrite]
|
16
|
+
save!(options[:outfile], output) if options[:outfile]
|
17
|
+
output
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def output!(output)
|
23
|
+
puts output
|
24
|
+
end
|
25
|
+
|
26
|
+
def overwrite!(infile, output)
|
27
|
+
raise('No file to overwrite') unless infile
|
28
|
+
File.write infile, output
|
29
|
+
end
|
30
|
+
|
31
|
+
def save!(outfile, output)
|
32
|
+
raise('No output file specified') unless outfile
|
33
|
+
File.write outfile, output
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
require 'active_support/core_ext/hash/deep_merge'
|
3
|
+
|
4
|
+
module Magma::Config
|
5
|
+
class MLT < ActiveSupport::HashWithIndifferentAccess
|
6
|
+
VERSION = 1
|
7
|
+
ALLOWED_KEYS = %w[
|
8
|
+
globals
|
9
|
+
scopes
|
10
|
+
type
|
11
|
+
version
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
attr_reader :data
|
15
|
+
|
16
|
+
def initialize(hash = {})
|
17
|
+
super({
|
18
|
+
globals: {},
|
19
|
+
scopes: {},
|
20
|
+
type: 'mlt',
|
21
|
+
version: VERSION,
|
22
|
+
}.merge(hash))
|
23
|
+
validate!
|
24
|
+
end
|
25
|
+
|
26
|
+
def globals
|
27
|
+
self[:globals]
|
28
|
+
end
|
29
|
+
|
30
|
+
def operations
|
31
|
+
raise 'needs to be resolved' unless resolved?
|
32
|
+
data.select { |key, _value| key[0] == '$' }
|
33
|
+
end
|
34
|
+
|
35
|
+
def resolve(context = {})
|
36
|
+
@data = context.reduce(globals.clone) do |res, (key, value)|
|
37
|
+
scope = scopes.fetch(key, {}).fetch(value, nil)
|
38
|
+
res.tap { |r| r.deep_merge!(scope) if scope }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def resolved?
|
43
|
+
data && true
|
44
|
+
end
|
45
|
+
|
46
|
+
def scopes
|
47
|
+
self[:scopes]
|
48
|
+
end
|
49
|
+
|
50
|
+
def transform(doc)
|
51
|
+
raise 'needs to be resolved' unless resolved?
|
52
|
+
operations.each do |key, obj|
|
53
|
+
# Skip if not prefixed with $
|
54
|
+
leader = key[0]
|
55
|
+
next unless leader == '$'
|
56
|
+
|
57
|
+
# Select node set
|
58
|
+
nodeset = doc.css(key[1..-1])
|
59
|
+
|
60
|
+
case obj
|
61
|
+
when Hash
|
62
|
+
obj.each do |name, value|
|
63
|
+
if value
|
64
|
+
nodeset.attr(name, value)
|
65
|
+
else
|
66
|
+
nodeset.remove_attr(name)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
text = obj.to_s
|
71
|
+
nodeset.each { |node| node.content = text }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
doc
|
75
|
+
end
|
76
|
+
|
77
|
+
def variables
|
78
|
+
raise 'needs to be resolved' unless resolved?
|
79
|
+
data.reject { |key, _value| key[0] == '$' }
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def validate!
|
85
|
+
extras = keys - ALLOWED_KEYS
|
86
|
+
raise "extra keys: #{extras}" unless extras.empty?
|
87
|
+
raise 'not type: mlt' unless self[:type] == 'mlt'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
data/lib/magma/config.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'magma/common'
|
2
|
+
require 'magma/utils'
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'securerandom'
|
5
|
+
|
6
|
+
module Magma
|
7
|
+
class Preparer
|
8
|
+
include Magma::Common
|
9
|
+
include Magma::Utils
|
10
|
+
|
11
|
+
def initialize(infile, options = {})
|
12
|
+
@infile = infile
|
13
|
+
@options = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
stabilize_producers!
|
18
|
+
handle_output! xml, options.merge(infile: infile)
|
19
|
+
xml
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
attr_accessor :infile, :options
|
25
|
+
|
26
|
+
def doc
|
27
|
+
@doc ||= Nokogiri::XML(source)
|
28
|
+
end
|
29
|
+
|
30
|
+
def log(message)
|
31
|
+
# Don't print the message if we're out-putting to STDOUT
|
32
|
+
puts message unless options[:print]
|
33
|
+
end
|
34
|
+
|
35
|
+
def resource_path
|
36
|
+
return Dir.pwd unless infile
|
37
|
+
File.dirname File.expand_path(infile)
|
38
|
+
end
|
39
|
+
|
40
|
+
def stabilize_producers! # rubocop:disable Metrics/AbcSize
|
41
|
+
map = Hash[doc.xpath('//producer').map do |producer|
|
42
|
+
id = producer.get_attribute 'id'
|
43
|
+
next nil if uuid? id
|
44
|
+
[producer.get_attribute('id'), uuid]
|
45
|
+
end.compact]
|
46
|
+
return if map.empty?
|
47
|
+
|
48
|
+
doc.traverse do |node|
|
49
|
+
id = node.get_attribute 'id'
|
50
|
+
case node.name
|
51
|
+
when 'producer'
|
52
|
+
if map[id]
|
53
|
+
log "Re-mapping producer##{id} id to #{map[id]}"
|
54
|
+
node.set_attribute('id', map[id])
|
55
|
+
|
56
|
+
node.search('property[name="resource"]').each do |property|
|
57
|
+
if File.file?(File.join(resource_path, property.content))
|
58
|
+
log "Expanding resource '#{resource_path}/#{property.content}'"
|
59
|
+
property.content = File.join(resource_path, property.content)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
producer = node.get_attribute 'producer'
|
65
|
+
if map[producer]
|
66
|
+
node.set_attribute('producer', map[producer])
|
67
|
+
log "Re-mapping #{node.name}#{id ? '#' + id : ''} producer to #{map[producer]}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def source
|
74
|
+
@source ||= read_file_or_stdin(infile) || raise('Need a template')
|
75
|
+
end
|
76
|
+
|
77
|
+
def uuid
|
78
|
+
SecureRandom.uuid
|
79
|
+
end
|
80
|
+
|
81
|
+
def xml
|
82
|
+
doc.to_xml
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'magma/utils'
|
2
|
+
require 'pry'
|
3
|
+
|
4
|
+
module Magma
|
5
|
+
class Renderer
|
6
|
+
SUPPORTED_FORMATS = %w[hls mp4].freeze
|
7
|
+
MELT = 'melt'.freeze
|
8
|
+
|
9
|
+
include Magma::Common
|
10
|
+
include Magma::Utils
|
11
|
+
|
12
|
+
def initialize(outfile, options)
|
13
|
+
@outfile = outfile
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
render!
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_accessor :options, :outfile
|
24
|
+
|
25
|
+
# Adds sane defaults to config
|
26
|
+
def add_defaults(options)
|
27
|
+
{
|
28
|
+
hls_list_size: 0,
|
29
|
+
start_number: 0,
|
30
|
+
}.merge(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Formats keys to melt arguments
|
34
|
+
def format(options)
|
35
|
+
options.map do |key, value|
|
36
|
+
[{
|
37
|
+
format: :f,
|
38
|
+
size: :s,
|
39
|
+
length: :hls_time,
|
40
|
+
}[key] || key, value].map(&:to_s).join('=')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Finds and constructs a melt invocation string
|
45
|
+
def melt(args)
|
46
|
+
bin = which(MELT) || raise("#{MELT} not found. Is MLT installed?")
|
47
|
+
"#{bin} #{args}"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Constructs melt arguments from options hash
|
51
|
+
def melt_args(options)
|
52
|
+
[
|
53
|
+
options[:infile],
|
54
|
+
"-consumer avformat:#{outfile}",
|
55
|
+
].concat(pipe(options, %i[
|
56
|
+
symbolize_keys
|
57
|
+
add_defaults
|
58
|
+
select
|
59
|
+
transform
|
60
|
+
table
|
61
|
+
format
|
62
|
+
]))
|
63
|
+
end
|
64
|
+
|
65
|
+
# Renders the project
|
66
|
+
def render!
|
67
|
+
cmd = melt melt_args(options.merge(outfile: outfile)).join(' ')
|
68
|
+
puts "Run: #{cmd}"
|
69
|
+
puts
|
70
|
+
|
71
|
+
run(cmd) do |_stdin, _stdout, stderr|
|
72
|
+
stderr.each("\r") do |line|
|
73
|
+
STDOUT.write "\r#{line}"
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Selects certain options
|
79
|
+
def select(options)
|
80
|
+
# Clone original
|
81
|
+
options = options.clone
|
82
|
+
|
83
|
+
# Handle related options
|
84
|
+
options.delete(:real_time) unless options.delete(:enable_real_time)
|
85
|
+
|
86
|
+
# Reject
|
87
|
+
options.select do |key, value|
|
88
|
+
!value.nil? && %i[
|
89
|
+
format
|
90
|
+
hls_list_size
|
91
|
+
real_time
|
92
|
+
length
|
93
|
+
preset
|
94
|
+
size
|
95
|
+
start_number
|
96
|
+
vcodec
|
97
|
+
].include?(key)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Prints a table and passes through the options hash
|
102
|
+
def table(options)
|
103
|
+
lpadding = options.keys.max_by(&:length).length + 2
|
104
|
+
rpadding = options.values.max_by { |v| v.to_s.length }.to_s.length
|
105
|
+
puts 'PROPERTY'.ljust(lpadding) + 'VALUE'
|
106
|
+
puts '=' * (lpadding + rpadding)
|
107
|
+
options.keys.sort.each do |key|
|
108
|
+
puts key.to_s.ljust(lpadding) + options[key].to_s
|
109
|
+
end
|
110
|
+
puts
|
111
|
+
options
|
112
|
+
end
|
113
|
+
|
114
|
+
# Transforms certain options values
|
115
|
+
def transform(options)
|
116
|
+
options.map do |key, value|
|
117
|
+
[key, ({
|
118
|
+
real_time: ->(x) { "-#{x}" },
|
119
|
+
}[key] || proc { |x| x }).call(value)]
|
120
|
+
end.to_h
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'magma/config/mlt'
|
2
|
+
require 'magma/common'
|
3
|
+
require 'magma/utils'
|
4
|
+
require 'liquid'
|
5
|
+
require 'nokogiri'
|
6
|
+
|
7
|
+
module Magma
|
8
|
+
class Templater
|
9
|
+
include Magma::Common
|
10
|
+
include Magma::Utils
|
11
|
+
|
12
|
+
def initialize(infile, options)
|
13
|
+
@infile = infile
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def call
|
18
|
+
pipe source, [
|
19
|
+
:template,
|
20
|
+
:render,
|
21
|
+
:parse,
|
22
|
+
:transform,
|
23
|
+
'.to_xml',
|
24
|
+
->(result) { handle_output!(result, options.merge(infile: infile)) },
|
25
|
+
]
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
attr_reader :infile, :options
|
31
|
+
|
32
|
+
def config
|
33
|
+
@config ||= Magma::Config::MLT.new(data).tap do |c|
|
34
|
+
c.resolve(options[:context] || {})
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def data
|
39
|
+
@data ||= options[:data_file].nil? ? {} : YAML.safe_load(File.read(options[:data_file]), [], [], true)
|
40
|
+
end
|
41
|
+
|
42
|
+
def source
|
43
|
+
@source ||= read_file_or_stdin(infile) || raise('Need a template')
|
44
|
+
end
|
45
|
+
|
46
|
+
### Pipeline
|
47
|
+
|
48
|
+
# Renders a Liquid template
|
49
|
+
def render(template)
|
50
|
+
template.render(config.variables.deep_merge(options[:globals]), strict_variables: true).tap do
|
51
|
+
if template.errors&.length&.positive?
|
52
|
+
puts template.errors
|
53
|
+
raise template.errors.map(&:to_s).join('; ')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Parses a template into a DOM
|
59
|
+
def parse(template)
|
60
|
+
Nokogiri::XML template
|
61
|
+
end
|
62
|
+
|
63
|
+
# Parses a source into a template
|
64
|
+
def template(source)
|
65
|
+
Liquid::Template.parse(source, error_mode: :strict)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Applies transformations to a document
|
69
|
+
def transform(doc)
|
70
|
+
config.transform doc
|
71
|
+
end
|
72
|
+
|
73
|
+
# Converts a docuemtn into XML
|
74
|
+
def xml(doc)
|
75
|
+
doc.to_xml
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/lib/magma/utils.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Magma
|
4
|
+
module Utils
|
5
|
+
# Reads a file or from STDIN if piped
|
6
|
+
def read_file_or_stdin(filename = nil)
|
7
|
+
filename.nil? ? !STDIN.tty? && STDIN.read : File.read(filename)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns whether a string is a UUID
|
11
|
+
def uuid?(uuid)
|
12
|
+
uuid_regex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/
|
13
|
+
uuid_regex =~ uuid.to_s.downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
# Applies methods/procs to an object in order
|
17
|
+
def pipe(object, methods = [])
|
18
|
+
methods.reduce(object) do |acc, method|
|
19
|
+
case method
|
20
|
+
when Proc || method.respond_to?(:call)
|
21
|
+
method.call(acc)
|
22
|
+
when Symbol
|
23
|
+
send(method, acc)
|
24
|
+
when String
|
25
|
+
raise "must start with '.'" unless method[0] == '.'
|
26
|
+
acc.send(method[1..-1].to_sym)
|
27
|
+
else
|
28
|
+
raise "unexpected pipe #{method}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Delegates to Open3
|
34
|
+
def run(*args, &block)
|
35
|
+
return Open3.popen3(*args, &block) if block_given?
|
36
|
+
Open3.popen3(*args)
|
37
|
+
end
|
38
|
+
|
39
|
+
# Symbolizes a hash's keys
|
40
|
+
def symbolize_keys(hash)
|
41
|
+
hash.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v }
|
42
|
+
end
|
43
|
+
|
44
|
+
# Cross-platform way of finding an executable in the $PATH
|
45
|
+
# Reference: https://stackoverflow.com/a/5471032/3557448
|
46
|
+
def which(cmd)
|
47
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
48
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
49
|
+
exts.each do |ext|
|
50
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
51
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/magma.rb
ADDED
data/magma.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require 'magma/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'magma_cli'
|
7
|
+
spec.version = Magma::VERSION
|
8
|
+
spec.authors = ['Allan Reyes']
|
9
|
+
spec.email = ['allanbreyes@users.noreply.github.com']
|
10
|
+
|
11
|
+
spec.summary = 'Magma CLI'
|
12
|
+
spec.description = 'Command-line interface for MLT templating and rendering'
|
13
|
+
spec.homepage = 'https://github.com/darbylabs/magma'
|
14
|
+
spec.license = 'LGPL-2.1'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(examples|features|spec|test)/})
|
18
|
+
end
|
19
|
+
spec.executables = ['magma']
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'activesupport', '~> 5.2'
|
23
|
+
spec.add_dependency 'liquid', '~> 4.0'
|
24
|
+
spec.add_dependency 'nokogiri', '~> 1.8'
|
25
|
+
spec.add_dependency 'thor', '~> 0.20'
|
26
|
+
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
30
|
+
end
|