stasis 0.1.0
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 +10 -0
- data/LICENSE +18 -0
- data/README.md +287 -0
- data/Rakefile +109 -0
- data/bin/stasis +30 -0
- data/config/gemsets.yml +9 -0
- data/config/gemspec.yml +17 -0
- data/lib/stasis.rb +291 -0
- data/lib/stasis/dev_mode.rb +55 -0
- data/lib/stasis/gems.rb +154 -0
- data/lib/stasis/plugin.rb +76 -0
- data/lib/stasis/plugins/before.rb +50 -0
- data/lib/stasis/plugins/helpers.rb +29 -0
- data/lib/stasis/plugins/ignore.rb +35 -0
- data/lib/stasis/plugins/instead.rb +15 -0
- data/lib/stasis/plugins/layout.rb +51 -0
- data/lib/stasis/plugins/priority.rb +41 -0
- data/lib/stasis/plugins/render.rb +71 -0
- data/lib/stasis/scope.rb +54 -0
- data/lib/stasis/scope/action.rb +25 -0
- data/lib/stasis/scope/controller.rb +62 -0
- data/lib/stasis/server.rb +90 -0
- data/site/arrow.png +0 -0
- data/site/controller.rb +72 -0
- data/site/github.png +0 -0
- data/site/index.html.haml +24 -0
- data/site/jquery-1.6.2.js +8982 -0
- data/site/stasis.css.scss +226 -0
- data/site/stasis.js.coffee +42 -0
- data/site/stasis.png +0 -0
- data/spec/fixtures/gemsets.yml +9 -0
- data/spec/fixtures/gemspec.yml +15 -0
- data/spec/fixtures/project/_partial.html.haml +1 -0
- data/spec/fixtures/project/before_render_partial.html.haml +1 -0
- data/spec/fixtures/project/before_render_text.html.haml +1 -0
- data/spec/fixtures/project/controller.rb +83 -0
- data/spec/fixtures/project/index.html.haml +16 -0
- data/spec/fixtures/project/layout.html.haml +3 -0
- data/spec/fixtures/project/layout_action.html.haml +1 -0
- data/spec/fixtures/project/layout_action_from_subdirectory.html.haml +1 -0
- data/spec/fixtures/project/layout_controller.html.haml +1 -0
- data/spec/fixtures/project/layout_controller_from_subdirectory.html.haml +1 -0
- data/spec/fixtures/project/no_controller/index.html.haml +12 -0
- data/spec/fixtures/project/not_dynamic.html +1 -0
- data/spec/fixtures/project/plugin.rb +16 -0
- data/spec/fixtures/project/subdirectory/_partial.html.haml +1 -0
- data/spec/fixtures/project/subdirectory/before_render_partial.html.haml +1 -0
- data/spec/fixtures/project/subdirectory/before_render_text.html.haml +1 -0
- data/spec/fixtures/project/subdirectory/controller.rb +66 -0
- data/spec/fixtures/project/subdirectory/ignore.html.haml +0 -0
- data/spec/fixtures/project/subdirectory/index.html.haml +14 -0
- data/spec/fixtures/project/subdirectory/layout.html.haml +3 -0
- data/spec/fixtures/project/subdirectory/layout_action.html.haml +1 -0
- data/spec/fixtures/project/subdirectory/layout_action_from_root.html.haml +1 -0
- data/spec/fixtures/project/subdirectory/layout_controller.html.haml +1 -0
- data/spec/fixtures/project/subdirectory/layout_controller_from_root.html.haml +1 -0
- data/spec/fixtures/project/time.html.haml +2 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/stasis/gems_spec.rb +249 -0
- data/spec/stasis/plugins/before_spec.rb +53 -0
- data/spec/stasis/plugins/helpers_spec.rb +16 -0
- data/spec/stasis/plugins/ignore_spec.rb +17 -0
- data/spec/stasis/plugins/layout_spec.rb +22 -0
- data/spec/stasis/plugins/priority_spec.rb +22 -0
- data/spec/stasis/plugins/render_spec.rb +23 -0
- data/spec/stasis/server_spec.rb +29 -0
- data/spec/stasis_spec.rb +46 -0
- data/stasis.gemspec +32 -0
- metadata +227 -0
data/config/gemsets.yml
ADDED
data/config/gemspec.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
name: stasis
|
2
|
+
version: 0.1.0
|
3
|
+
authors:
|
4
|
+
- Winton Welsh
|
5
|
+
email: mail@wintoni.us
|
6
|
+
homepage: http://wintoni.us
|
7
|
+
summary: Markup-agnostic static site generator
|
8
|
+
description: A markup-agnostic static site generator.
|
9
|
+
dependencies:
|
10
|
+
- directory_watcher
|
11
|
+
- redis
|
12
|
+
- slop
|
13
|
+
- tilt
|
14
|
+
- yajl-ruby
|
15
|
+
development_dependencies:
|
16
|
+
- rake
|
17
|
+
- rspec
|
data/lib/stasis.rb
ADDED
@@ -0,0 +1,291 @@
|
|
1
|
+
# **Stasis** is a dynamic framework for static sites.
|
2
|
+
|
3
|
+
### Prerequisites
|
4
|
+
|
5
|
+
require 'fileutils'
|
6
|
+
|
7
|
+
# `Stasis::Gems` handles loading of rubygems and gems listed in [config/gemsets.yml][ge].
|
8
|
+
#
|
9
|
+
# [ge]: https://github.com/winton/stasis/blob/master/config/gemsets.yml
|
10
|
+
|
11
|
+
require File.dirname(__FILE__) + '/stasis/gems'
|
12
|
+
|
13
|
+
# [Slim][sl] ships with its own [Tilt][ti] integration. If the user has [Slim][sl]
|
14
|
+
# installed, require it, otherwise don't worry about it.
|
15
|
+
#
|
16
|
+
# [sl]: http://slim-lang.com/
|
17
|
+
# [ti]: https://github.com/rtomayko/tilt
|
18
|
+
|
19
|
+
begin
|
20
|
+
require 'slim'
|
21
|
+
rescue Exception => e
|
22
|
+
end
|
23
|
+
|
24
|
+
# Activate the [Tilt][ti] gem.
|
25
|
+
|
26
|
+
Stasis::Gems.activate %w(tilt)
|
27
|
+
|
28
|
+
# Add the project directory to the load paths.
|
29
|
+
|
30
|
+
$:.unshift File.dirname(__FILE__)
|
31
|
+
|
32
|
+
# Require all Stasis library files.
|
33
|
+
|
34
|
+
require 'stasis/dev_mode'
|
35
|
+
require 'stasis/plugin'
|
36
|
+
require 'stasis/server'
|
37
|
+
|
38
|
+
require 'stasis/scope'
|
39
|
+
require 'stasis/scope/action'
|
40
|
+
require 'stasis/scope/controller'
|
41
|
+
|
42
|
+
require 'stasis/plugins/before'
|
43
|
+
require 'stasis/plugins/helpers'
|
44
|
+
require 'stasis/plugins/ignore'
|
45
|
+
require 'stasis/plugins/instead'
|
46
|
+
require 'stasis/plugins/layout'
|
47
|
+
require 'stasis/plugins/priority'
|
48
|
+
require 'stasis/plugins/render'
|
49
|
+
|
50
|
+
### Public Interface
|
51
|
+
|
52
|
+
class Stasis
|
53
|
+
|
54
|
+
# `Action` -- changes with each iteration of the main loop within `Stasis#render`.
|
55
|
+
attr_accessor :action
|
56
|
+
|
57
|
+
# `Controller` -- set to the same instance for the lifetime of the `Stasis` instance.
|
58
|
+
attr_accessor :controller
|
59
|
+
|
60
|
+
# `String` -- the destination path passed to `Stasis.new`.
|
61
|
+
attr_accessor :destination
|
62
|
+
|
63
|
+
# `String` -- changes with each iteration of the main loop within `Stasis#render`.
|
64
|
+
attr_accessor :path
|
65
|
+
|
66
|
+
# `Array` -- all paths in the project that Stasis will act upon.
|
67
|
+
attr_accessor :paths
|
68
|
+
|
69
|
+
# `Options` -- options passed to `Stasis.new`.
|
70
|
+
attr_accessor :options
|
71
|
+
|
72
|
+
# `Array` -- `Plugin` instances.
|
73
|
+
attr_accessor :plugins
|
74
|
+
|
75
|
+
# `String` -- the root path passed to `Stasis.new`.
|
76
|
+
attr_accessor :root
|
77
|
+
|
78
|
+
def initialize(root, *args)
|
79
|
+
@options = {}
|
80
|
+
@options = args.pop if args.last.is_a?(::Hash)
|
81
|
+
|
82
|
+
@root = File.expand_path(root)
|
83
|
+
@destination = args[0] || @root + '/public'
|
84
|
+
@destination = File.expand_path(@destination, @root)
|
85
|
+
|
86
|
+
# Create an `Array` of paths that Stasis will act upon.
|
87
|
+
@paths = Dir["#{@root}/**/*"]
|
88
|
+
|
89
|
+
# Reject paths that are directories or within the destination directory.
|
90
|
+
@paths.reject! do |path|
|
91
|
+
!File.file?(path) || path[0..@destination.length-1] == @destination
|
92
|
+
end
|
93
|
+
|
94
|
+
# Create plugin instances.
|
95
|
+
@plugins = find_plugins.collect { |klass| klass.new(self) }
|
96
|
+
|
97
|
+
# Create a controller instance.
|
98
|
+
@controller = Controller.new(self)
|
99
|
+
end
|
100
|
+
|
101
|
+
def render(*only)
|
102
|
+
collect = {}
|
103
|
+
render_options = {}
|
104
|
+
|
105
|
+
if only.last.is_a?(::Hash)
|
106
|
+
render_options = only.pop
|
107
|
+
end
|
108
|
+
|
109
|
+
# Resolve paths given via the `only` parameter.
|
110
|
+
only = only.inject([]) do |array, path|
|
111
|
+
# If `path` is a regular expression...
|
112
|
+
if path.is_a?(::Regexp)
|
113
|
+
array << path
|
114
|
+
# If `root + path` exists...
|
115
|
+
elsif (path = File.expand_path(path, root)) && File.exists?(path)
|
116
|
+
array << path
|
117
|
+
# If `path` exists...
|
118
|
+
elsif File.exists?(path)
|
119
|
+
array << path
|
120
|
+
end
|
121
|
+
array
|
122
|
+
end
|
123
|
+
|
124
|
+
if only.empty?
|
125
|
+
# Remove old generated files.
|
126
|
+
FileUtils.rm_rf(destination)
|
127
|
+
end
|
128
|
+
|
129
|
+
# Reject paths that are controllers.
|
130
|
+
@paths.reject! do |path|
|
131
|
+
if File.basename(path) == 'controller.rb'
|
132
|
+
# Add controller to `Controller` instance.
|
133
|
+
@controller._add(path)
|
134
|
+
true
|
135
|
+
else
|
136
|
+
false
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Trigger all plugin `before_all` events.
|
141
|
+
trigger(:before_all)
|
142
|
+
|
143
|
+
@paths.uniq.each do |path|
|
144
|
+
@path = path
|
145
|
+
|
146
|
+
# If `only` parameters given...
|
147
|
+
unless only.empty?
|
148
|
+
# Skip iteration unless there is a match.
|
149
|
+
next unless only.any? do |only|
|
150
|
+
# Regular expression match.
|
151
|
+
(only.is_a?(::Regexp) && @path =~ only) ||
|
152
|
+
(
|
153
|
+
only.is_a?(::String) && (
|
154
|
+
# File match.
|
155
|
+
@path == only ||
|
156
|
+
# Directory match.
|
157
|
+
@path[0..only.length-1] == only
|
158
|
+
)
|
159
|
+
)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# Create an `Action` instance, the scope for rendering the view.
|
164
|
+
@action = Action.new(self)
|
165
|
+
|
166
|
+
# Set the extension if the `@path` extension is supported by [Tilt][ti].
|
167
|
+
ext =
|
168
|
+
Tilt.mappings.keys.detect do |ext|
|
169
|
+
File.extname(@path)[1..-1] == ext
|
170
|
+
end
|
171
|
+
|
172
|
+
# Trigger all plugin `before_render` events.
|
173
|
+
trigger(:before_render)
|
174
|
+
|
175
|
+
# Skip if `@path` set to `nil`.
|
176
|
+
next unless @path
|
177
|
+
|
178
|
+
# Render the view.
|
179
|
+
view =
|
180
|
+
# If the path has an extension supported by [Tilt][ti]...
|
181
|
+
if ext
|
182
|
+
# If the controller calls `render` within the `before` block for this
|
183
|
+
# path, receive output from `@action._render`.
|
184
|
+
#
|
185
|
+
# Otherwise, render the file located at `@path`.
|
186
|
+
output = @action._render || @action.render(@path, :callback => false)
|
187
|
+
|
188
|
+
# If a layout was specified via the `layout` method...
|
189
|
+
if @action._layout
|
190
|
+
# Render the layout with a block for the layout to `yield` to.
|
191
|
+
@action.render(@action._layout) { output }
|
192
|
+
# If a layout was not specified...
|
193
|
+
else
|
194
|
+
output
|
195
|
+
end
|
196
|
+
# If the path does not have an extension supported by [Tilt][ti] and `render` was
|
197
|
+
# called within the `before` block for this path...
|
198
|
+
elsif @action._render
|
199
|
+
@action._render
|
200
|
+
end
|
201
|
+
|
202
|
+
# Trigger all plugin `after_render` events.
|
203
|
+
trigger(:after_render)
|
204
|
+
|
205
|
+
# Cut the `root` out of the `path` to get the relative destination.
|
206
|
+
relative = @path[root.length..-1]
|
207
|
+
|
208
|
+
# Add `destination` (as specified from `Stasis.new`) to front of relative
|
209
|
+
# destination.
|
210
|
+
dest = "#{destination}#{relative}"
|
211
|
+
|
212
|
+
# Cut off the extension if the extension is supported by [Tilt][ti].
|
213
|
+
dest =
|
214
|
+
if ext && File.extname(dest) == ".#{ext}"
|
215
|
+
dest[0..-1*ext.length-2]
|
216
|
+
else
|
217
|
+
dest
|
218
|
+
end
|
219
|
+
|
220
|
+
# Create the directories leading up to the destination.
|
221
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
222
|
+
|
223
|
+
# If markup was rendered...
|
224
|
+
if view
|
225
|
+
# Write the rendered markup to the destination.
|
226
|
+
if render_options[:write] != false
|
227
|
+
File.open(dest, 'w') do |f|
|
228
|
+
f.write(view)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
# Collect render output.
|
232
|
+
if render_options[:collect]
|
233
|
+
collect[relative[1..-1]] = view
|
234
|
+
end
|
235
|
+
# If markup was not rendered and the path exists...
|
236
|
+
elsif File.exists?(@path)
|
237
|
+
# Copy the file located at the path to the destination path.
|
238
|
+
if render_options[:write] != false
|
239
|
+
FileUtils.cp(@path, dest)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Trigger all plugin `after_all` events, passing the `Stasis` instance.
|
245
|
+
trigger(:after_all)
|
246
|
+
|
247
|
+
# Unset class-level instance variables.
|
248
|
+
@action, @path = nil, nil
|
249
|
+
|
250
|
+
# Respond with collected render output if `collect` option given.
|
251
|
+
collect if render_options[:collect]
|
252
|
+
end
|
253
|
+
|
254
|
+
# Add a plugin to all existing controller instances. This method should be called by
|
255
|
+
# all external plugins.
|
256
|
+
def self.register(plugin)
|
257
|
+
ObjectSpace.each_object(::Stasis) do |stasis|
|
258
|
+
plugin = plugin.new(stasis)
|
259
|
+
stasis.plugins << plugin
|
260
|
+
stasis.controller._bind_plugin(plugin, :controller_method)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
# Trigger an event on every plugin in the controller.
|
265
|
+
def trigger(type)
|
266
|
+
each_priority do |priority|
|
267
|
+
@controller._send_to_plugin(priority, type)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
private
|
272
|
+
|
273
|
+
# Iterate through plugin priority integers (sorted) and yield each to a block.
|
274
|
+
def each_priority(&block)
|
275
|
+
priorities = @plugins.collect do |plugin|
|
276
|
+
plugin.class._priority
|
277
|
+
end
|
278
|
+
priorities.uniq.sort.each(&block)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Returns an `Array` of `Stasis::Plugin` classes.
|
282
|
+
def find_plugins
|
283
|
+
plugins = []
|
284
|
+
ObjectSpace.each_object(Class) do |klass|
|
285
|
+
if klass < ::Stasis::Plugin
|
286
|
+
plugins << klass
|
287
|
+
end
|
288
|
+
end
|
289
|
+
plugins
|
290
|
+
end
|
291
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
Stasis::Gems.activate %w(directory_watcher)
|
2
|
+
require 'directory_watcher'
|
3
|
+
|
4
|
+
class Stasis
|
5
|
+
class DevMode
|
6
|
+
|
7
|
+
def initialize(dir, options={})
|
8
|
+
trap("INT") { exit }
|
9
|
+
|
10
|
+
puts "\nDevelopment mode enabled: #{dir}"
|
11
|
+
|
12
|
+
@dir = dir
|
13
|
+
@options = options
|
14
|
+
|
15
|
+
render
|
16
|
+
|
17
|
+
dw = DirectoryWatcher.new(@stasis.root)
|
18
|
+
dw.interval = 1
|
19
|
+
|
20
|
+
Dir.chdir(@stasis.root) do
|
21
|
+
within_public = @stasis.destination[0..@stasis.root.length-1] == @stasis.root
|
22
|
+
rel_public = @stasis.destination[@stasis.root.length+1..-1] rescue nil
|
23
|
+
dw.glob = Dir["*"].inject(["*"]) do |array, path|
|
24
|
+
if File.directory?(path) && (!within_public || path != rel_public)
|
25
|
+
array << "#{path}/**/*"
|
26
|
+
end
|
27
|
+
array
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
dw.add_observer do |*events|
|
32
|
+
modified = events.detect { |e| e[:type] == :modified }
|
33
|
+
render if modified
|
34
|
+
end
|
35
|
+
|
36
|
+
dw.start
|
37
|
+
loop { sleep 1000 }
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def render
|
43
|
+
puts "\n[#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}] Regenerating #{@options[:only] ? @options[:only].join(', ') : 'project'}..."
|
44
|
+
begin
|
45
|
+
@stasis = Stasis.new(*[ @dir, @options[:public], @options ].compact)
|
46
|
+
@stasis.render(*@options[:only])
|
47
|
+
rescue Exception => e
|
48
|
+
puts "\n[#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}] Error: #{e.message}`"
|
49
|
+
puts "\t#{e.backtrace.join("\n\t")}"
|
50
|
+
else
|
51
|
+
puts "\n[#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}] Complete"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/stasis/gems.rb
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
unless defined?(Stasis::Gems)
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
class Stasis
|
6
|
+
module Gems
|
7
|
+
class <<self
|
8
|
+
|
9
|
+
attr_accessor :config
|
10
|
+
attr_reader :gemset, :gemsets, :versions
|
11
|
+
|
12
|
+
class SimpleStruct
|
13
|
+
attr_reader :hash
|
14
|
+
|
15
|
+
def initialize(hash)
|
16
|
+
@hash = hash
|
17
|
+
@hash.each do |key, value|
|
18
|
+
self.class.send(:define_method, key) { @hash[key] }
|
19
|
+
self.class.send(:define_method, "#{key}=") { |v| @hash[key] = v }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Gems.config = SimpleStruct.new(
|
25
|
+
:gemsets => [ "#{File.expand_path('../../../', __FILE__)}/config/gemsets.yml" ],
|
26
|
+
:gemspec => "#{File.expand_path('../../../', __FILE__)}/config/gemspec.yml",
|
27
|
+
:warn => true
|
28
|
+
)
|
29
|
+
|
30
|
+
def activate(*gems)
|
31
|
+
begin
|
32
|
+
require 'rubygems' unless defined?(::Gem)
|
33
|
+
rescue LoadError
|
34
|
+
puts "rubygems library could not be required" if @config.warn
|
35
|
+
end
|
36
|
+
|
37
|
+
self.gemset ||= gemset_from_loaded_specs
|
38
|
+
|
39
|
+
gems.flatten.collect { |g| g.to_sym }.each do |name|
|
40
|
+
version = @versions[name]
|
41
|
+
vendor = File.expand_path("../../../vendor/#{name}/lib", __FILE__)
|
42
|
+
if File.exists?(vendor)
|
43
|
+
$:.unshift vendor
|
44
|
+
elsif defined?(gem)
|
45
|
+
gem name.to_s, version
|
46
|
+
else
|
47
|
+
puts "#{name} #{"(#{version})" if version} failed to activate" if @config.warn
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def dependencies
|
53
|
+
dependency_filter(@gemspec.dependencies, @gemset)
|
54
|
+
end
|
55
|
+
|
56
|
+
def development_dependencies
|
57
|
+
dependency_filter(@gemspec.development_dependencies, @gemset)
|
58
|
+
end
|
59
|
+
|
60
|
+
def gemset=(gemset)
|
61
|
+
if gemset
|
62
|
+
@gemset = gemset.to_sym
|
63
|
+
|
64
|
+
@gemsets = @config.gemsets.reverse.collect { |config|
|
65
|
+
if config.is_a?(::String)
|
66
|
+
YAML::load(File.read(config)) rescue {}
|
67
|
+
elsif config.is_a?(::Hash)
|
68
|
+
config
|
69
|
+
end
|
70
|
+
}.inject({}) do |hash, config|
|
71
|
+
deep_merge(hash, symbolize_keys(config))
|
72
|
+
end
|
73
|
+
|
74
|
+
@versions = (@gemsets[gemspec.name.to_sym] || {}).inject({}) do |hash, (key, value)|
|
75
|
+
if !value.is_a?(::Hash) && value
|
76
|
+
hash[key] = value
|
77
|
+
elsif key == @gemset
|
78
|
+
(value || {}).each { |k, v| hash[k] = v }
|
79
|
+
end
|
80
|
+
hash
|
81
|
+
end
|
82
|
+
else
|
83
|
+
@gemset = nil
|
84
|
+
@gemsets = nil
|
85
|
+
@versions = nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def gemset_names
|
90
|
+
(
|
91
|
+
[ :default ] +
|
92
|
+
@gemsets[gemspec.name.to_sym].inject([]) { |array, (key, value)|
|
93
|
+
array.push(key) if value.is_a?(::Hash) || value.nil?
|
94
|
+
array
|
95
|
+
}
|
96
|
+
).uniq
|
97
|
+
end
|
98
|
+
|
99
|
+
def gemspec(reload=false)
|
100
|
+
if @gemspec && !reload
|
101
|
+
@gemspec
|
102
|
+
else
|
103
|
+
data = YAML::load(File.read(@config.gemspec)) rescue {}
|
104
|
+
@gemspec = SimpleStruct.new(data)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def deep_merge(first, second)
|
111
|
+
merger = lambda do |key, v1, v2|
|
112
|
+
Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
|
113
|
+
end
|
114
|
+
first.merge(second, &merger)
|
115
|
+
end
|
116
|
+
|
117
|
+
def dependency_filter(dependencies, match)
|
118
|
+
(dependencies || []).inject([]) { |array, value|
|
119
|
+
if value.is_a?(::Hash)
|
120
|
+
array += value[match.to_s] if value[match.to_s]
|
121
|
+
else
|
122
|
+
array << value
|
123
|
+
end
|
124
|
+
array
|
125
|
+
}.uniq.collect(&:to_sym)
|
126
|
+
end
|
127
|
+
|
128
|
+
def gemset_from_loaded_specs
|
129
|
+
if defined?(Gem)
|
130
|
+
Gem.loaded_specs.each do |name, spec|
|
131
|
+
if name == gemspec.name
|
132
|
+
return :default
|
133
|
+
elsif name[0..gemspec.name.length] == "#{gemspec.name}-"
|
134
|
+
return name[gemspec.name.length+1..-1].to_sym
|
135
|
+
end
|
136
|
+
end
|
137
|
+
:default
|
138
|
+
else
|
139
|
+
:none
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def symbolize_keys(hash)
|
144
|
+
return {} unless hash.is_a?(::Hash)
|
145
|
+
hash.inject({}) do |options, (key, value)|
|
146
|
+
value = symbolize_keys(value) if value.is_a?(::Hash)
|
147
|
+
options[(key.to_sym rescue key) || key] = value
|
148
|
+
options
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|