guard-templates 0.0.1
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +152 -0
- data/Rakefile +1 -0
- data/guard-templates.gemspec +25 -0
- data/lib/engines/jade-runtime.js +123 -0
- data/lib/engines/jade.js +3143 -0
- data/lib/guard/compilers.rb +13 -0
- data/lib/guard/templates/templates/Guardfile +11 -0
- data/lib/guard/templates.rb +115 -0
- data/spec/guard-templates-spec.rb +202 -0
- metadata +159 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'execjs'
|
2
|
+
|
3
|
+
module Guard
|
4
|
+
class Templates < Guard
|
5
|
+
module Compilers
|
6
|
+
def self.compile_jade(str)
|
7
|
+
jade = File.read(File.join(Pathname.new(__FILE__).dirname.to_s, '../engines/jade.js'))
|
8
|
+
ExecJS.compile("window = {}; #{jade}").eval("window.jade.compile(#{str.dump}, {client:true, compileDebug:false}).toString()")
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# Example guardfile for guard-templates
|
2
|
+
#
|
3
|
+
# by default, output to a single .js file in public/javascript/templates.js
|
4
|
+
# if you'd like to compile each template to an individual .js file,
|
5
|
+
# change :output to a directory path instead
|
6
|
+
#
|
7
|
+
# see https://github.com/thegreatape/guard-templates for more options
|
8
|
+
guard 'templates', :output => 'public/javascript/templates.js', :namespace => 'MyApp' do
|
9
|
+
# change this regex to match your source files
|
10
|
+
watch(/app\/javascripts\/templates\/(.*)\.jade$/)
|
11
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "guard"
|
2
|
+
require "guard/guard"
|
3
|
+
require 'guard/compilers'
|
4
|
+
|
5
|
+
module Guard
|
6
|
+
class Templates < Guard
|
7
|
+
|
8
|
+
DEFAULTS = {
|
9
|
+
:namespace => 'this'
|
10
|
+
}
|
11
|
+
|
12
|
+
# Initialize a Guard.
|
13
|
+
# @param [Array<Guard::Watcher>] watchers the Guard file watchers
|
14
|
+
# @param [Hash] options the custom Guard options
|
15
|
+
def initialize(watchers = [], options = {})
|
16
|
+
@watchers = watchers
|
17
|
+
@options = DEFAULTS.clone.merge(options)
|
18
|
+
@single_file_mode = @options[:output].match(/\.js$/)
|
19
|
+
super(watchers, @options)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Call once when Guard starts. Please override initialize method to init stuff.
|
23
|
+
# @raise [:task_has_failed] when start has failed
|
24
|
+
def start
|
25
|
+
run_all
|
26
|
+
end
|
27
|
+
|
28
|
+
# Called when `stop|quit|exit|s|q|e + enter` is pressed (when Guard quits).
|
29
|
+
# @raise [:task_has_failed] when stop has failed
|
30
|
+
def stop
|
31
|
+
end
|
32
|
+
|
33
|
+
# Called when `reload|r|z + enter` is pressed.
|
34
|
+
# This method should be mainly used for "reload" (really!) actions like reloading passenger/spork/bundler/...
|
35
|
+
# @raise [:task_has_failed] when reload has failed
|
36
|
+
def reload
|
37
|
+
end
|
38
|
+
|
39
|
+
# Called when just `enter` is pressed
|
40
|
+
# This method should be principally used for long action like running all specs/tests/...
|
41
|
+
# @raise [:task_has_failed] when run_all has failed
|
42
|
+
def run_all
|
43
|
+
run_on_change(Watcher.match_files(self, Dir.glob('**/*')))
|
44
|
+
end
|
45
|
+
|
46
|
+
# Called on file(s) modifications that the Guard watches.
|
47
|
+
# @param [Array<String>] paths the changes files or paths
|
48
|
+
# @raise [:task_has_failed] when run_on_change has failed
|
49
|
+
def run_on_change(paths)
|
50
|
+
templates = {}
|
51
|
+
paths.each do |path|
|
52
|
+
@watchers.each do |watcher|
|
53
|
+
if target = get_target(path, watcher)
|
54
|
+
contents = File.read(path)
|
55
|
+
if @single_file_mode
|
56
|
+
templates[target] = contents
|
57
|
+
else
|
58
|
+
dir = Pathname.new(target[:path]).dirname.to_s
|
59
|
+
FileUtils.mkdir_p(dir) if !File.exist?(dir)
|
60
|
+
File.open(target[:path], 'w') do |f|
|
61
|
+
f.write("#{@options[:namespace]}['#{target[:name]}'] = #{compile(contents, target[:type])}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
if @single_file_mode
|
68
|
+
File.open(@options[:output], 'w') do |f|
|
69
|
+
js = templates.map{|target,content| "#{target[:name].dump}: #{compile(content, target[:type])}" }.join(",\n")
|
70
|
+
f.write "#{@options[:namespace]}.templates = {#{js}}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Called on file(s) deletions that the Guard watches.
|
76
|
+
# @param [Array<String>] paths the deleted files or paths
|
77
|
+
# @raise [:task_has_failed] when run_on_change has failed
|
78
|
+
def run_on_deletion(paths)
|
79
|
+
matched = false
|
80
|
+
paths.each do |path|
|
81
|
+
@watchers.each do |watcher|
|
82
|
+
if target = get_target(path, watcher)
|
83
|
+
matched = true
|
84
|
+
FileUtils.rm target[:path] unless @single_file_mode
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# this is slow, but works. would be better to do a eval + series of deletes,
|
90
|
+
# but how to re-serialize the js object?
|
91
|
+
run_all if @single_file_mode && matched
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
def get_target(path, watcher)
|
96
|
+
if match = path.match(watcher.pattern)
|
97
|
+
subpath = match[1]
|
98
|
+
jspath = File.join(@options[:output], "#{subpath}.js")
|
99
|
+
|
100
|
+
{:name => subpath,
|
101
|
+
:type => File.extname(path).gsub(/^\./,''),
|
102
|
+
:path => jspath}
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def compile(str, type)
|
107
|
+
if Compilers.methods.include?("compile_#{type}")
|
108
|
+
Compilers.send("compile_#{type}", str)
|
109
|
+
else
|
110
|
+
str.dump
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler/setup"
|
3
|
+
require 'execjs'
|
4
|
+
require 'fakefs/safe'
|
5
|
+
|
6
|
+
require 'guard/templates'
|
7
|
+
require 'guard/watcher'
|
8
|
+
|
9
|
+
# ExecJS needs real filesystem access to find the js engine
|
10
|
+
def eval_js(str, context='')
|
11
|
+
FakeFS.deactivate!
|
12
|
+
result = ExecJS.compile(context).eval(str)
|
13
|
+
FakeFS.activate!
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
module ExecJS
|
18
|
+
class << self
|
19
|
+
alias :old_compile :compile
|
20
|
+
def compile(source, *args)
|
21
|
+
FakeFS.deactivate!
|
22
|
+
result = self.old_compile(source, *args)
|
23
|
+
FakeFS.activate!
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
ExecJS.runtime.class.const_get('Context').class_eval do
|
30
|
+
alias :old_eval :eval
|
31
|
+
def eval(source, options={})
|
32
|
+
FakeFS.deactivate!
|
33
|
+
result = old_eval(source, options)
|
34
|
+
FakeFS.activate!
|
35
|
+
result
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
describe Guard::Templates do
|
41
|
+
before(:each) do
|
42
|
+
# have to write js libs to FakeFS post-fake-activation
|
43
|
+
js_src = File.join(Pathname.new(__FILE__).dirname.to_s, '../lib/engines/')
|
44
|
+
libs = Dir.glob(File.join(js_src, "*.js")).map do |path|
|
45
|
+
[File.basename(path), File.read(path)]
|
46
|
+
end
|
47
|
+
FakeFS.activate!
|
48
|
+
FileUtils.mkdir_p 'lib/engines'
|
49
|
+
FileUtils.mkdir_p 'javascripts/templates'
|
50
|
+
FileUtils.mkdir_p 'public/templates'
|
51
|
+
libs.each do |name, content|
|
52
|
+
File.open("lib/engines/#{name}", 'w') {|f| f.write(content)}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
after(:each) do
|
57
|
+
FileUtils.rm_rf 'javascripts'
|
58
|
+
FileUtils.rm_rf 'public'
|
59
|
+
FakeFS.deactivate!
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#run_on_change" do
|
63
|
+
before(:each) do
|
64
|
+
@content = "<div>\n {{foo}}\n</div>"
|
65
|
+
@template = 'javascripts/templates/home.handlebars'
|
66
|
+
File.open(@template, 'w') {|f| f.write(@content)}
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should create a new file with the stringifed template" do
|
70
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.handlebars/)],
|
71
|
+
:output => 'public/templates')
|
72
|
+
@guard_templates.run_on_change [@template]
|
73
|
+
File.exists?('public/templates/home.js').should == true
|
74
|
+
File.read('public/templates/home.js').should == "this['home'] = #{@content.dump}"
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should write the template with a namespace" do
|
78
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.handlebars/)],
|
79
|
+
:output => 'public/templates',
|
80
|
+
:namespace => 'App.Jawesome')
|
81
|
+
@guard_templates.run_on_change [@template]
|
82
|
+
File.read('public/templates/home.js').should == "App.Jawesome['home'] = #{@content.dump}"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should write the templates to a single file when output has a .js extension" do
|
86
|
+
wombat_template = 'javascripts/templates/wombat.handlebars'
|
87
|
+
wombat_content = '<span>{{wombat}}</span>'
|
88
|
+
File.open(wombat_template, 'w') {|f| f.write(wombat_content)}
|
89
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.handlebars/)],
|
90
|
+
:output => 'public/templates/templates.js')
|
91
|
+
@guard_templates.run_on_change [@template, wombat_template]
|
92
|
+
File.exists?('public/templates/home.js').should == false
|
93
|
+
File.exists?('public/templates/wombat.js').should == false
|
94
|
+
File.exists?('public/templates/templates.js').should == true
|
95
|
+
templates = eval_js File.read('public/templates/templates.js')
|
96
|
+
templates.keys.should =~ ['home', 'wombat']
|
97
|
+
templates['wombat'].should == wombat_content
|
98
|
+
templates['home'].should == @content
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should compile jade to native functions" do
|
102
|
+
jade_template = 'javascripts/templates/jade-test.jade'
|
103
|
+
jade_content = '.greetings O HAI'
|
104
|
+
File.open(jade_template, 'w') {|f| f.write(jade_content)}
|
105
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.jade/)],
|
106
|
+
:namespace => 'app',
|
107
|
+
:output => 'public/templates')
|
108
|
+
@guard_templates.run_on_change [jade_template]
|
109
|
+
File.exists?('public/templates/jade-test.js').should == true
|
110
|
+
compiled = File.read('public/templates/jade-test.js')
|
111
|
+
jade = File.read('lib/engines/jade-runtime.js')
|
112
|
+
context = %{var window = {}, app = {};
|
113
|
+
#{jade}
|
114
|
+
#{compiled} }
|
115
|
+
fn = "app['jade-test']()"
|
116
|
+
eval_js(fn, context).should == '<div class="greetings">O HAI</div>'
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should compile jade to native functions in single-file mode" do
|
120
|
+
jade_template = 'javascripts/templates/jade-test.jade'
|
121
|
+
jade_content = '.greetings O HAI'
|
122
|
+
File.open(jade_template, 'w') {|f| f.write(jade_content)}
|
123
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.jade/)],
|
124
|
+
:namespace => 'app',
|
125
|
+
:output => 'public/templates/all.js')
|
126
|
+
@guard_templates.run_on_change [jade_template]
|
127
|
+
File.exists?('public/templates/all.js').should == true
|
128
|
+
File.exists?('public/templates/jade-test.js').should == false
|
129
|
+
compiled = File.read('public/templates/all.js')
|
130
|
+
jade = File.read('lib/engines/jade-runtime.js')
|
131
|
+
context = %{var window = {}, app = {};
|
132
|
+
#{jade}
|
133
|
+
#{compiled} }
|
134
|
+
fn = "app.templates['jade-test']()"
|
135
|
+
eval_js(fn, context).should == '<div class="greetings">O HAI</div>'
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
describe "#run_on_deletion" do
|
140
|
+
it "should delete output files with source files are deleted" do
|
141
|
+
src_path = 'javascripts/templates/home.handlebars'
|
142
|
+
dst_path = 'public/templates/home.js'
|
143
|
+
File.open(src_path, 'w') {|f| f.write('<div>{foo}</div>')}
|
144
|
+
File.open(dst_path, 'w') {|f| f.write('var home = "<div>{foo}</div>"')}
|
145
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.handlebars/)],
|
146
|
+
:output => 'public/templates')
|
147
|
+
FileUtils.rm(src_path)
|
148
|
+
@guard_templates.run_on_deletion(src_path)
|
149
|
+
File.exists?(dst_path).should == false
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should delete multiple files correctly" do
|
153
|
+
srcs = ['foo', 'bar', 'goats']
|
154
|
+
srcs.each do |s|
|
155
|
+
File.open("javascripts/templates/#{s}.handlebars", 'w') {|f| f.write('<div>{foo}</div>')}
|
156
|
+
File.open("public/templates/#{s}.js", 'w') {|f| f.write("this['#{s}'] = '<div>{foo}</div>'")}
|
157
|
+
end
|
158
|
+
File.open("javascripts/templates/dont_delete_me_bro.handlebars", 'w') {|f| f.write('<div>{foo}</div>')}
|
159
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.handlebars/)],
|
160
|
+
:output => 'public/templates')
|
161
|
+
|
162
|
+
srcs.each{|s| FileUtils.rm "javascripts/templates/#{s}.handlebars"}
|
163
|
+
@guard_templates.run_on_deletion(srcs.map{|s| "javascripts/templates/#{s}.handlebars"})
|
164
|
+
srcs.each{|s| File.exists?("public/templates/#{s}.js").should == false}
|
165
|
+
end
|
166
|
+
|
167
|
+
it "should delete entries in single file mode" do
|
168
|
+
src_path = 'javascripts/templates/home.handlebars'
|
169
|
+
File.open(src_path, 'w') {|f| f.write("<div>{foo}</div>")}
|
170
|
+
File.open('javascripts/templates/foo.handlebars', 'w') {|f| f.write('foo')}
|
171
|
+
|
172
|
+
dst_path = 'public/templates.js'
|
173
|
+
File.open(dst_path, 'w') {|f| f.write("this['templates'] = {home: 'home', foo: 'bar'}")}
|
174
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.handlebars/)],
|
175
|
+
:output => 'public/templates.js')
|
176
|
+
eval_js(File.read(dst_path)).keys.should =~ ['home', 'foo']
|
177
|
+
|
178
|
+
FileUtils.rm(src_path)
|
179
|
+
@guard_templates.run_on_deletion([src_path])
|
180
|
+
templates = eval_js(File.read(dst_path))
|
181
|
+
templates.keys.should == ['foo']
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe '#run_all' do
|
186
|
+
it "should compile everything" do
|
187
|
+
paths = ['foo', 'bar/baz', 'duck/duck/go']
|
188
|
+
paths.each do |p|
|
189
|
+
target = "javascripts/templates/#{p}.handlebars"
|
190
|
+
FileUtils.mkdir_p Pathname.new(target).dirname.to_s
|
191
|
+
File.open(target, 'w') {|f| f.write(p)}
|
192
|
+
end
|
193
|
+
@guard_templates = Guard::Templates.new([Guard::Watcher.new(/javascripts\/templates\/(.*)\.handlebars/)],
|
194
|
+
:output => 'public/templates/')
|
195
|
+
|
196
|
+
@guard_templates.run_all
|
197
|
+
paths.each do |p|
|
198
|
+
File.exists?("public/templates/#{p}.js").should == true
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
metadata
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: guard-templates
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Thomas Mayfield
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-04-01 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: guard
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: execjs
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: json
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
type: :development
|
75
|
+
version_requirements: *id004
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: rspec
|
78
|
+
prerelease: false
|
79
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
type: :development
|
89
|
+
version_requirements: *id005
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: fakefs
|
92
|
+
prerelease: false
|
93
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 3
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
type: :development
|
103
|
+
version_requirements: *id006
|
104
|
+
description: Guard plugin for smart, automatic compilation of your Javascript template files into usable Javascript
|
105
|
+
email:
|
106
|
+
- Thomas.Mayfield@gmail.com
|
107
|
+
executables: []
|
108
|
+
|
109
|
+
extensions: []
|
110
|
+
|
111
|
+
extra_rdoc_files: []
|
112
|
+
|
113
|
+
files:
|
114
|
+
- .gitignore
|
115
|
+
- Gemfile
|
116
|
+
- README.md
|
117
|
+
- Rakefile
|
118
|
+
- guard-templates.gemspec
|
119
|
+
- lib/engines/jade-runtime.js
|
120
|
+
- lib/engines/jade.js
|
121
|
+
- lib/guard/compilers.rb
|
122
|
+
- lib/guard/templates.rb
|
123
|
+
- lib/guard/templates/templates/Guardfile
|
124
|
+
- spec/guard-templates-spec.rb
|
125
|
+
homepage: ""
|
126
|
+
licenses: []
|
127
|
+
|
128
|
+
post_install_message:
|
129
|
+
rdoc_options: []
|
130
|
+
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
none: false
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
hash: 3
|
139
|
+
segments:
|
140
|
+
- 0
|
141
|
+
version: "0"
|
142
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
143
|
+
none: false
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
hash: 3
|
148
|
+
segments:
|
149
|
+
- 0
|
150
|
+
version: "0"
|
151
|
+
requirements: []
|
152
|
+
|
153
|
+
rubyforge_project: guard-templates
|
154
|
+
rubygems_version: 1.8.17
|
155
|
+
signing_key:
|
156
|
+
specification_version: 3
|
157
|
+
summary: Javascript template compilation via Guard
|
158
|
+
test_files:
|
159
|
+
- spec/guard-templates-spec.rb
|