machined 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/machined.rb CHANGED
@@ -10,6 +10,7 @@ module Machined
10
10
  autoload :Sprocket, 'machined/sprocket'
11
11
  autoload :StaticCompiler, 'machined/static_compiler'
12
12
  autoload :Utils, 'machined/utils'
13
+ autoload :Watcher, 'machined/watcher'
13
14
 
14
15
  module Helpers
15
16
  autoload :AssetTagHelpers, 'machined/helpers/asset_tag_helpers'
@@ -19,6 +20,10 @@ module Machined
19
20
  autoload :RenderHelpers, 'machined/helpers/render_helpers'
20
21
  end
21
22
 
23
+ module Middleware
24
+ autoload :Static, 'machined/middleware/static'
25
+ end
26
+
22
27
  module Processors
23
28
  autoload :FrontMatterProcessor, 'machined/processors/front_matter_processor'
24
29
  autoload :LayoutProcessor, 'machined/processors/layout_processor'
@@ -2,6 +2,8 @@ require 'ostruct'
2
2
  require 'pathname'
3
3
  require 'active_support/cache'
4
4
  require 'active_support/core_ext/hash/reverse_merge'
5
+ require 'active_support/core_ext/module/delegation'
6
+ require 'active_support/string_inquirer'
5
7
  require 'crush'
6
8
  require 'tilt'
7
9
 
@@ -9,12 +11,18 @@ module Machined
9
11
  class Environment
10
12
  include Initializable
11
13
 
14
+ # Delegate some common configuration accessors
15
+ # to the config object.
16
+ delegate :root, :config_path, :output_path, :lib_path, :environment,
17
+ :to => :config
18
+
12
19
  # Default options for a Machined environment.
13
20
  DEFAULT_OPTIONS = {
14
21
  # Global configuration
15
22
  :root => '.',
16
23
  :config_path => 'machined.rb',
17
24
  :output_path => 'public',
25
+ :lib_path => 'lib',
18
26
  :environment => 'development',
19
27
  :cache => nil,
20
28
  :skip_bundle => false,
@@ -70,27 +78,19 @@ module Machined
70
78
  # through the `#helpers` method.
71
79
  attr_reader :context_helpers
72
80
 
73
- # When the Machined environment is compiling static files,
74
- # this will reference the `Machined::StaticCompiler` which handles
75
- # looping through the available files and generating them.
76
- attr_reader :static_compiler
77
-
78
- # A reference to the root directory the Machined
79
- # environment is run from.
80
- attr_reader :root
81
-
82
- # A reference to the directory the Machined environment
83
- # compiles its files to.
84
- attr_reader :output_path
81
+ # When the Machined environment is used as a Rack server, this
82
+ # will reference the actual `Machined::Server` instance that handles
83
+ # the requests.
84
+ attr_reader :server
85
85
 
86
86
  # An `Array` of the Sprockets environments (actually `Machined::Sprocket`
87
87
  # instances) that are the core of a Machined environment.
88
88
  attr_reader :sprockets
89
89
 
90
- # When the Machined environment is used as a Rack server, this
91
- # will reference the actual `Machined::Server` instance that handles
92
- # the requests.
93
- attr_reader :server
90
+ # When the Machined environment is compiling static files,
91
+ # this will reference the `Machined::StaticCompiler` which handles
92
+ # looping through the available files and generating them.
93
+ attr_reader :static_compiler
94
94
 
95
95
  # Creates a new Machined environment. It sets up three default
96
96
  # sprockets:
@@ -102,11 +102,14 @@ module Machined
102
102
  # layouts and partials go.
103
103
  #
104
104
  def initialize(options = {})
105
- @config = OpenStruct.new DEFAULT_OPTIONS.dup.merge(options)
106
- @root = Pathname.new(config.root).expand_path
107
- @output_path = root.join config.output_path
108
- @sprockets = []
109
- @context_helpers = []
105
+ @config = OpenStruct.new DEFAULT_OPTIONS.dup.merge(options)
106
+ @sprockets = []
107
+ @context_helpers = []
108
+ config.root = Pathname.new(config.root).expand_path
109
+ config.config_path = root.join config.config_path
110
+ config.output_path = root.join config.output_path
111
+ config.lib_path = root.join config.lib_path
112
+ config.environment = ActiveSupport::StringInquirer.new(config.environment)
110
113
 
111
114
  run_initializers self
112
115
  end
@@ -120,10 +123,20 @@ module Machined
120
123
  if File.exist? ENV['BUNDLE_GEMFILE']
121
124
  require 'bundler/setup'
122
125
  require 'sprockets'
123
- Bundler.require :default, config.environment.to_sym
126
+ Bundler.require :default, environment.to_sym
124
127
  end
125
128
  end
126
129
 
130
+ # Appends the lib directory to the load path.
131
+ # Changes to files in this directory will trigger a reload
132
+ # of the Machined environment.
133
+ initializer :setup_autoloading do
134
+ next if config.skip_autoloading || !lib_path.exist?
135
+
136
+ require 'active_support/dependencies'
137
+ ActiveSupport::Dependencies.autoload_paths = [lib_path.to_s]
138
+ end
139
+
127
140
  # Create and append the default `assets` sprocket.
128
141
  # This sprocket mimics the asset pipeline in Rails 3.1.
129
142
  initializer :create_assets_sprocket do
@@ -159,11 +172,10 @@ module Machined
159
172
  # available at this point, but not fully configured. This is so
160
173
  # you can actually configure the sprockets with this file.
161
174
  initializer :eval_config_file do
162
- config_file = root.join config.config_path
163
- instance_eval config_file.read if config_file.exist?
175
+ instance_eval config_path.read if config_path.exist?
164
176
 
165
177
  # This could be changed in the config file
166
- @output_path = root.join config.output_path
178
+ config.output_path = root.join config.output_path
167
179
  remove_sprocket(:pages) if config.assets_only && @pages
168
180
  end
169
181
 
@@ -291,6 +303,22 @@ module Machined
291
303
  static_compiler.compile
292
304
  end
293
305
 
306
+ # Reloads the environment. This will re-evaluate the config file &
307
+ # clear the current cache.
308
+ def reload
309
+ # Make sure we have a fresh cache after we reload
310
+ config.cache.clear if config.cache.respond_to?(:clear)
311
+
312
+ # Reload dependencies as well, if necessary
313
+ ActiveSupport::Dependencies.clear if defined?(ActiveSupport::Dependencies)
314
+
315
+ # Use current configuration, but skip bundle and autoloading initializers
316
+ current_config = config.marshal_dump.dup
317
+ current_config.merge! :skip_bundle => true#, :skip_autoloading => true)
318
+
319
+ initialize current_config
320
+ end
321
+
294
322
  # Creates a Machined sprocket with the given +name+ and +options+
295
323
  # and appends it to the #sprockets list. This will also create
296
324
  # an accessor with the given name that references the created sprocket.
@@ -306,7 +334,6 @@ module Machined
306
334
  def append_sprocket(name, options = {}, &block)
307
335
  create_sprocket(name, options, &block).tap do |sprocket|
308
336
  sprockets.push(sprocket).uniq!
309
- server and server.remap
310
337
  end
311
338
  end
312
339
 
@@ -315,7 +342,6 @@ module Machined
315
342
  def prepend_sprocket(name, options = {}, &block)
316
343
  create_sprocket(name, options, &block).tap do |sprocket|
317
344
  sprockets.unshift(sprocket).uniq!
318
- server and server.remap
319
345
  end
320
346
  end
321
347
 
@@ -325,7 +351,6 @@ module Machined
325
351
  if sprocket = get_sprocket(name)
326
352
  sprockets.delete sprocket
327
353
  set_sprocket(name, nil)
328
- server and server.remap
329
354
  end
330
355
  end
331
356
 
@@ -60,11 +60,11 @@ module Machined
60
60
  # Run each initializer with the given args
61
61
  # yielded to each initializer's block.
62
62
  def run_initializers(*args)
63
- return if @initializers_run
63
+ # return if @initializers_run
64
64
  self.class.initializers.each do |initializer|
65
65
  initializer.run self, *args
66
66
  end
67
- @initializers_run = true
67
+ # @initializers_run = true
68
68
  end
69
69
  end
70
70
  end
@@ -0,0 +1,46 @@
1
+ require 'rack'
2
+
3
+ module Machined
4
+ module Middleware
5
+ # Machined::Middleware::Static serves static files
6
+ # from the given directory. If no static file is
7
+ # found, the request gets passed on to the next
8
+ # middleware or application. It's basically
9
+ # a simplified version of ActionDispatch::Static.
10
+ class Static
11
+ def initialize(app, root = '.', cache_control = nil)
12
+ @app = app
13
+ @root = File.expand_path(root)
14
+ @compiled_root = /^#{Regexp.escape(@root)}/
15
+ @file_server = ::Rack::File.new(@root, cache_control)
16
+ end
17
+
18
+ def call(env)
19
+ case env['REQUEST_METHOD']
20
+ when 'GET', 'HEAD'
21
+ path = env['PATH_INFO'].chomp('/')
22
+ if match = match?(path)
23
+ env['PATH_INFO'] = match
24
+ return @file_server.call(env)
25
+ end
26
+ end
27
+
28
+ @app.call(env)
29
+ end
30
+
31
+ protected
32
+
33
+ def match?(path)
34
+ full_path = path.empty? ? @root : File.join(@root, path)
35
+ matches = Dir[full_path + '{,.html,/index.html}']
36
+ match = matches.detect { |f| File.file?(f) }
37
+
38
+ if match
39
+ ::Rack::Utils.escape match.sub(@compiled_root, '')
40
+ else
41
+ nil
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -1,3 +1,4 @@
1
+ require 'active_support/file_update_checker'
1
2
  require 'rack'
2
3
 
3
4
  module Machined
@@ -10,37 +11,59 @@ module Machined
10
11
  # up the processed files.
11
12
  def initialize(machined)
12
13
  @machined = machined
13
- @files = Rack::File.new(machined.output_path)
14
- remap
14
+
15
+ if machined.environment.development?
16
+ # Configure watchable files
17
+ files = []
18
+ files << machined.config_path if machined.config_path.exist?
19
+
20
+ # Configure watchable dirs
21
+ dirs = {}
22
+ dirs[machined.lib_path.to_s] = [:rb] if machined.lib_path.exist?
23
+
24
+ # Setup file watching using ActiveSupport::FileUpdateChecker
25
+ @reloader = ActiveSupport::FileUpdateChecker.new(files, dirs) do
26
+ machined.reload
27
+ reload
28
+ end
29
+ end
30
+
31
+ reload
15
32
  end
16
33
 
17
34
  # Using the URLMap, determine which sprocket
18
35
  # should handle the request and then...let it
19
36
  # handle it.
20
37
  def call(env)
21
- refresh if machined.config.environment == 'development'
22
- response = @url_map.call(env)
23
- response = @files.call(env) if response.first == 404
24
- response
38
+ @reloader.execute_if_updated if machined.environment.development?
39
+ @app.call(env)
25
40
  end
26
41
 
27
- # Remaps the Machined environment's current
28
- # sprockets using `Rack::URLMap`.
29
- def remap
30
- map = {}
31
- machined.sprockets.each do |sprocket|
32
- next unless sprocket.compile?
33
- map[sprocket.config.url] = sprocket
34
- end
35
- @url_map = Rack::URLMap.new map
42
+ # Rebuilds the Rack app with the current Machined
43
+ # configuration.
44
+ def reload
45
+ @app = to_app
36
46
  end
37
47
 
38
48
  protected
39
49
 
40
- # Refreshes the environment
41
- def refresh
42
- machined.sprockets.each do |sprocket|
43
- sprocket.send :expire_index!
50
+ # Creates a Rack app with the current Machined
51
+ # environment configuration.
52
+ def to_app # :nodoc:
53
+ Rack::Builder.new.tap do |app|
54
+ app.use Middleware::Static, machined.output_path
55
+ app.run Rack::URLMap.new(sprockets_map)
56
+ end
57
+ end
58
+
59
+ # Maps the Machined environment's current
60
+ # sprockets for use with `Rack::URLMap`.
61
+ def sprockets_map # :nodoc:
62
+ {}.tap do |map|
63
+ machined.sprockets.each do |sprocket|
64
+ next unless sprocket.compile?
65
+ map[sprocket.config.url] = sprocket
66
+ end
44
67
  end
45
68
  end
46
69
  end
@@ -1,7 +1,4 @@
1
- require 'bundler'
2
- Bundler.require :default, config.environment.to_sym
3
-
4
- if config.environment == 'production'
1
+ if environment.production?
5
2
  # Compress javascripts and stylesheets
6
3
  config.compress = true
7
4
 
@@ -1,3 +1,3 @@
1
1
  module Machined
2
- VERSION = '0.8.0'
2
+ VERSION = '0.9.0'
3
3
  end
@@ -104,10 +104,7 @@ describe Machined::CLI do
104
104
  within_construct do |c|
105
105
  machined_cli 'new my_site'
106
106
  File.read('my_site/machined.rb').should == <<-CONTENT.unindent
107
- require 'bundler'
108
- Bundler.require :default, config.environment.to_sym
109
-
110
- if config.environment == 'production'
107
+ if environment.production?
111
108
  # Compress javascripts and stylesheets
112
109
  config.compress = true
113
110
 
@@ -3,14 +3,14 @@ require 'spec_helper'
3
3
  describe Machined::Context do
4
4
  describe '#machined' do
5
5
  it 'returns a reference to the Machined environment' do
6
- context.machined.should be(machined)
6
+ build_context.machined.should be(machined)
7
7
  end
8
8
  end
9
9
 
10
10
  describe '#config' do
11
11
  it "returns a reference to the Machined environment's configuration" do
12
12
  machined.config.layout = 'application'
13
- context.config.layout.should == 'application'
13
+ build_context.config.layout.should == 'application'
14
14
  end
15
15
  end
16
16
  end
@@ -8,7 +8,7 @@ describe Machined::Environment do
8
8
  config.output_path = 'site'
9
9
  append_sprocket :updates
10
10
  CONTENT
11
- machined.config.output_path.should == 'site'
11
+ machined.config.output_path.should == Pathname.new('site').expand_path
12
12
  machined.updates.should be_a(Machined::Sprocket)
13
13
  end
14
14
  end
@@ -83,7 +83,7 @@ describe Machined::Environment do
83
83
  end
84
84
  end
85
85
 
86
- context.hello.should == 'world'
86
+ build_context.hello.should == 'world'
87
87
  end
88
88
 
89
89
  it 'adds methods defined in the given module to the Context' do
@@ -93,7 +93,81 @@ describe Machined::Environment do
93
93
  end
94
94
  end
95
95
  machined.helpers helper
96
- context.hello.should == 'world'
96
+ build_context.hello.should == 'world'
97
+ end
98
+ end
99
+
100
+ describe '#reload' do
101
+ it 'knows when helpers are changed' do
102
+ within_construct do |c|
103
+ c.file 'machined.rb', 'helpers do; def hello; "hello"; end; end'
104
+ build_context.hello.should == 'hello'
105
+
106
+ modify 'machined.rb', 'helpers do; def hello; "world"; end; end'
107
+ machined.reload
108
+ build_context.hello.should == 'world'
109
+ end
110
+ end
111
+
112
+ it 'knows when configuration is changed' do
113
+ within_construct do |c|
114
+ c.file 'machined.rb'
115
+ machined.output_path.should == c.join('public')
116
+
117
+ modify 'machined.rb', 'config.output_path = "output"'
118
+ machined.reload
119
+ machined.output_path.should == c.join('output')
120
+ end
121
+ end
122
+
123
+ it 'does not re-append sprockets' do
124
+ within_construct do |c|
125
+ c.file 'machined.rb'
126
+ machined.sprockets.length.should == 3
127
+
128
+ modify 'machined.rb', 'config.output_path = "output"'
129
+ machined.reload
130
+ machined.sprockets.length.should == 3
131
+ end
132
+ end
133
+
134
+ it 're-evaluates assets when configuration changes' do
135
+ within_construct do |c|
136
+ c.file 'machined.rb', 'helpers do; def hello; "hello"; end; end'
137
+ c.file 'pages/index.html.erb', '<%= hello %>'
138
+ machined.pages['index.html'].to_s.should == 'hello'
139
+
140
+ modify 'machined.rb', 'helpers do; def hello; "world"; end; end'
141
+ machined.reload
142
+ machined.pages['index.html'].to_s.should == 'world'
143
+ end
144
+ end
145
+
146
+ it 'knows when a lib file changes' do
147
+ within_construct do |c|
148
+ c.file 'lib/hello.rb', 'module Hello; def hello; "hello"; end; end'
149
+ c.file 'machined.rb', 'helpers Hello'
150
+ machined :skip_autoloading => false
151
+ build_context.hello.should == 'hello'
152
+
153
+ modify 'lib/hello.rb', 'module Hello; def hello; "world"; end; end'
154
+ machined.reload
155
+ build_context.hello.should == 'world'
156
+ end
157
+ end
158
+ end
159
+
160
+ describe '#environment' do
161
+ it 'is wrapped in String inquirer' do
162
+ machined :environment => 'development'
163
+ machined.environment.development?.should be_true
164
+ machined.environment.production?.should be_false
165
+ machined.environment.test?.should be_false
166
+
167
+ machined :environment => 'production', :reload => true
168
+ machined.environment.development?.should be_false
169
+ machined.environment.production?.should be_true
170
+ machined.environment.test?.should be_false
97
171
  end
98
172
  end
99
173
 
@@ -246,16 +320,25 @@ describe Machined::Environment do
246
320
  end
247
321
  end
248
322
  end
323
+
324
+ context 'with a js_compressor set' do
325
+ it 'compresses using that compressor' do
326
+ within_construct do |c|
327
+ c.file 'assets/javascripts/main.js', 'var app = {};'
328
+ c.file 'machined.rb', 'config.js_compressor = :packr'
329
+ Crush::Packr.should_receive(:compress).with("var app = {};\n").and_return('compressed')
330
+ machined.assets['main.js'].to_s.should == 'compressed'
331
+ end
332
+ end
333
+ end
249
334
  end
250
335
 
251
- context 'with a js_compressor set' do
252
- it 'compresses using that compressor' do
253
- within_construct do |c|
254
- c.file 'assets/javascripts/main.js', 'var app = {};'
255
- c.file 'machined.rb', 'config.js_compressor = :packr'
256
- Crush::Packr.should_receive(:compress).with("var app = {};\n").and_return('compressed')
257
- machined.assets['main.js'].to_s.should == 'compressed'
258
- end
336
+ it 'autoloads files from the lib directory' do
337
+ within_construct do |c|
338
+ c.file 'lib/hello.rb', 'module Hello; def hello; "hello"; end; end'
339
+ c.file 'machined.rb', 'helpers Hello'
340
+ machined :skip_autoloading => false
341
+ build_context.hello.should == 'hello'
259
342
  end
260
343
  end
261
344
  end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Machined::Helpers::AssetTagHelpers do
4
+ let(:context) { build_context }
5
+
4
6
  describe '#asset_path' do
5
7
  context 'with URIs' do
6
8
  it 'returns URIs untouched' do
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Machined::Helpers::LocalsHelpers do
4
+ let(:context) { build_context }
5
+
4
6
  describe '#locals=' do
5
7
  it 'sets psuedo local variables' do
6
8
  context.locals = { :text => 'Hello World', :body => nil }
@@ -19,14 +19,14 @@ describe Machined::Initializable do
19
19
  array.should == [ 1, 2, 3 ]
20
20
  end
21
21
 
22
- it 'runs initializers only once' do
23
- count = 0
24
- BasicInitializer.initializer(:count) { count += 1 }
25
- basic = BasicInitializer.new
26
- basic.run_initializers
27
- basic.run_initializers
28
- count.should == 1
29
- end
22
+ # it 'runs initializers only once' do
23
+ # count = 0
24
+ # BasicInitializer.initializer(:count) { count += 1 }
25
+ # basic = BasicInitializer.new
26
+ # basic.run_initializers
27
+ # basic.run_initializers
28
+ # count.should == 1
29
+ # end
30
30
 
31
31
  it 'executes in the instance scope' do
32
32
  BasicInitializer.initializer(:init_count) { @count = 0 }
@@ -0,0 +1,56 @@
1
+ require 'spec_helper'
2
+
3
+ describe Machined::Middleware::Static do
4
+ include Rack::Test::Methods
5
+
6
+ let(:root) { create_construct }
7
+ after(:each) { root.destroy! }
8
+
9
+ let(:app) do
10
+ Rack::Builder.new.tap do |app|
11
+ app.use Machined::Middleware::Static, root, 'public, max-age=60'
12
+ app.run Proc.new { |env| [200, {'Content-Type' => 'text/plain'}, ['Hello, World!']] }
13
+ end.to_app
14
+ end
15
+
16
+ it 'serves dynamic content' do
17
+ get('/nofile').body.should == 'Hello, World!'
18
+ end
19
+
20
+ it 'sets cache control headers' do
21
+ root.file 'file.txt', 'File Content'
22
+ get('/file.txt').headers['Cache-Control'].should == 'public, max-age=60'
23
+ end
24
+
25
+ it 'serves static files in the root directory' do
26
+ root.file 'file.txt', 'File Content'
27
+ get('/file.txt').body.should == 'File Content'
28
+ end
29
+
30
+ it 'serves static files in a subdirectory' do
31
+ root.file 'sub/directory/file.txt', 'Subdirectory File Content'
32
+ get('/sub/directory/file.txt').body.should == 'Subdirectory File Content'
33
+ end
34
+
35
+ it 'serves static index file in the root directory' do
36
+ root.file 'index.html', 'Static Index Content'
37
+ get('/index.html').body.should == 'Static Index Content'
38
+ get('/index').body.should == 'Static Index Content'
39
+ get('/').body.should == 'Static Index Content'
40
+ get('').body.should == 'Static Index Content'
41
+ end
42
+
43
+ it 'serves static index file in directory' do
44
+ root.file 'foo/index.html', 'Static Index Content in Directory'
45
+ get('/foo/index.html').body.should == 'Static Index Content in Directory'
46
+ get('/foo/').body.should == 'Static Index Content in Directory'
47
+ get('/foo').body.should == 'Static Index Content in Directory'
48
+ end
49
+
50
+ it 'serves static html file in directory' do
51
+ root.file 'foo/bar.html', 'HTML Content in Directory'
52
+ get('/foo/bar.html').body.should == 'HTML Content in Directory'
53
+ get('/foo/bar/').body.should == 'HTML Content in Directory'
54
+ get('/foo/bar').body.should == 'HTML Content in Directory'
55
+ end
56
+ end
@@ -25,7 +25,7 @@ describe Machined::Server do
25
25
  end
26
26
  end
27
27
 
28
- it 'serves up pages as the base url' do
28
+ it 'serves up pages at the base url' do
29
29
  within_construct do |c|
30
30
  c.file 'pages/index.html', "<h1>Hello World</h1>\n"
31
31
  c.file 'pages/about.html', "<h1>About Us</h1>\n"
@@ -57,8 +57,6 @@ describe Machined::Server do
57
57
  dir = c.directory 'updates'
58
58
  dir.file 'new-site.html', "<h1>Hello World</h1>\n"
59
59
 
60
- get '/'
61
-
62
60
  machined.append_sprocket :updates, :url => '/updates' do |updates|
63
61
  updates.append_path dir
64
62
  updates.register_mime_type 'text/html', '.html'
@@ -94,4 +92,30 @@ describe Machined::Server do
94
92
  last_response.body.should == "<h1>Hello World</h1>\n"
95
93
  end
96
94
  end
95
+
96
+ context 'reloading' do
97
+ it 'knows when the configuration changes' do
98
+ within_construct do |c|
99
+ c.file 'machined.rb', 'helpers do; def hello; "hello"; end; end'
100
+ c.file 'pages/index.html.erb', '<%= hello %>'
101
+ get('/').body.should == 'hello'
102
+
103
+ modify 'machined.rb', 'helpers do; def hello; "world"; end; end'
104
+ get('/').body.should == 'world'
105
+ end
106
+ end
107
+
108
+ it 'knows when a lib file changes' do
109
+ within_construct do |c|
110
+ c.file 'lib/hello.rb', 'module Hello; def hello; "hello"; end; end'
111
+ c.file 'machined.rb', 'helpers Hello'
112
+ c.file 'pages/index.html.erb', '<%= hello %>'
113
+ machined :skip_autoloading => false
114
+ get('/').body.should == 'hello'
115
+
116
+ modify 'lib/hello.rb', 'module Hello; def hello; "world"; end; end'
117
+ get('/').body.should == 'world'
118
+ end
119
+ end
120
+ end
97
121
  end
@@ -5,7 +5,8 @@ module Machined
5
5
  module SpecHelpers
6
6
  # Convenience method for creating a new Machined environment
7
7
  def machined(config = {})
8
- @machined ||= Machined::Environment.new(config.reverse_merge(:skip_bundle => true))
8
+ @machined = nil if config.delete(:reload)
9
+ @machined ||= Machined::Environment.new(config.reverse_merge(:skip_bundle => true, :skip_autoloading => true))
9
10
  end
10
11
 
11
12
  # Convenience method for creating a new Machined sprocket,
@@ -16,13 +17,11 @@ module Machined
16
17
  end
17
18
 
18
19
  # Returns a fresh context, that can be used to test helpers.
19
- def context(logical_path = 'application.js', options = {})
20
- @context ||= begin
21
- pathname = options[:pathname] || Pathname.new(File.join('assets', logical_path)).expand_path
22
- env = options[:env] || machined.assets
23
-
24
- env.context_class.new env, logical_path, pathname
25
- end
20
+ def build_context(logical_path = 'application.js', options = {})
21
+ pathname = options[:pathname] || Pathname.new('assets').join(logical_path).expand_path
22
+ env = options[:env] || machined.assets
23
+
24
+ env.context_class.new env, logical_path, pathname
26
25
  end
27
26
 
28
27
  # Runs the CLI with the given args.
@@ -32,6 +31,15 @@ module Machined
32
31
  }
33
32
  end
34
33
 
34
+ # Modifies the given file
35
+ def modify(file, content = nil)
36
+ Pathname.new(file).tap do |file|
37
+ file.open('w') { |f| f.write(content) } if content
38
+ future = Time.now + 60
39
+ file.utime future, future
40
+ end
41
+ end
42
+
35
43
  # Captures the given stream and returns it:
36
44
  #
37
45
  # stream = capture(:stdout) { puts 'Cool' }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: machined
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-20 00:00:00.000000000 Z
12
+ date: 2012-05-04 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sprockets
16
- requirement: &-1071292608 !ruby/object:Gem::Requirement
16
+ requirement: &70108802349040 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.4.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *-1071292608
24
+ version_requirements: *70108802349040
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: sprockets-helpers
27
- requirement: &-1071293098 !ruby/object:Gem::Requirement
27
+ requirement: &70108802344840 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 0.4.0
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *-1071293098
35
+ version_requirements: *70108802344840
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sprockets-sass
38
- requirement: &-1071293648 !ruby/object:Gem::Requirement
38
+ requirement: &70108802341200 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 0.8.0
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *-1071293648
46
+ version_requirements: *70108802341200
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: padrino-helpers
49
- requirement: &-1071294118 !ruby/object:Gem::Requirement
49
+ requirement: &70108802338900 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: 0.10.5
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *-1071294118
57
+ version_requirements: *70108802338900
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: activesupport
60
- requirement: &-1071294378 !ruby/object:Gem::Requirement
60
+ requirement: &70108802336740 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 3.2.3
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *-1071294378
68
+ version_requirements: *70108802336740
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: i18n
71
- requirement: &-1071294698 !ruby/object:Gem::Requirement
71
+ requirement: &70108802334600 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 0.6.0
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *-1071294698
79
+ version_requirements: *70108802334600
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: thor
82
- requirement: &-1071295248 !ruby/object:Gem::Requirement
82
+ requirement: &70108802333200 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 0.14.6
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *-1071295248
90
+ version_requirements: *70108802333200
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: crush
93
- requirement: &-1071295628 !ruby/object:Gem::Requirement
93
+ requirement: &70108802331000 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ~>
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: 0.3.3
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *-1071295628
101
+ version_requirements: *70108802331000
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rspec
104
- requirement: &-1071295908 !ruby/object:Gem::Requirement
104
+ requirement: &70108802329400 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ~>
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: 2.9.0
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *-1071295908
112
+ version_requirements: *70108802329400
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: rack-test
115
- requirement: &-1071296548 !ruby/object:Gem::Requirement
115
+ requirement: &70108802327300 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ~>
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: 0.6.1
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *-1071296548
123
+ version_requirements: *70108802327300
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: test-construct
126
- requirement: &-1071833678 !ruby/object:Gem::Requirement
126
+ requirement: &70108802325260 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ~>
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: 1.2.0
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *-1071833678
134
+ version_requirements: *70108802325260
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: unindent
137
- requirement: &-1071834008 !ruby/object:Gem::Requirement
137
+ requirement: &70108802324420 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ~>
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: '1.0'
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *-1071834008
145
+ version_requirements: *70108802324420
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: sprockets-plugin
148
- requirement: &-1071834328 !ruby/object:Gem::Requirement
148
+ requirement: &70108802323340 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ~>
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: 0.2.1
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *-1071834328
156
+ version_requirements: *70108802323340
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: haml
159
- requirement: &-1071834568 !ruby/object:Gem::Requirement
159
+ requirement: &70108802322060 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ! '>='
@@ -164,10 +164,10 @@ dependencies:
164
164
  version: '0'
165
165
  type: :development
166
166
  prerelease: false
167
- version_requirements: *-1071834568
167
+ version_requirements: *70108802322060
168
168
  - !ruby/object:Gem::Dependency
169
169
  name: sass
170
- requirement: &-1071834818 !ruby/object:Gem::Requirement
170
+ requirement: &70108802320040 !ruby/object:Gem::Requirement
171
171
  none: false
172
172
  requirements:
173
173
  - - ! '>='
@@ -175,10 +175,10 @@ dependencies:
175
175
  version: '0'
176
176
  type: :development
177
177
  prerelease: false
178
- version_requirements: *-1071834818
178
+ version_requirements: *70108802320040
179
179
  - !ruby/object:Gem::Dependency
180
180
  name: slim
181
- requirement: &-1071835058 !ruby/object:Gem::Requirement
181
+ requirement: &70108802317920 !ruby/object:Gem::Requirement
182
182
  none: false
183
183
  requirements:
184
184
  - - ! '>='
@@ -186,10 +186,10 @@ dependencies:
186
186
  version: '0'
187
187
  type: :development
188
188
  prerelease: false
189
- version_requirements: *-1071835058
189
+ version_requirements: *70108802317920
190
190
  - !ruby/object:Gem::Dependency
191
191
  name: erubis
192
- requirement: &-1071835298 !ruby/object:Gem::Requirement
192
+ requirement: &70108802316100 !ruby/object:Gem::Requirement
193
193
  none: false
194
194
  requirements:
195
195
  - - ! '>='
@@ -197,10 +197,10 @@ dependencies:
197
197
  version: '0'
198
198
  type: :development
199
199
  prerelease: false
200
- version_requirements: *-1071835298
200
+ version_requirements: *70108802316100
201
201
  - !ruby/object:Gem::Dependency
202
202
  name: rdiscount
203
- requirement: &-1071835618 !ruby/object:Gem::Requirement
203
+ requirement: &70108802314360 !ruby/object:Gem::Requirement
204
204
  none: false
205
205
  requirements:
206
206
  - - ! '>='
@@ -208,10 +208,10 @@ dependencies:
208
208
  version: '0'
209
209
  type: :development
210
210
  prerelease: false
211
- version_requirements: *-1071835618
211
+ version_requirements: *70108802314360
212
212
  - !ruby/object:Gem::Dependency
213
213
  name: uglifier
214
- requirement: &-1071835948 !ruby/object:Gem::Requirement
214
+ requirement: &70108802312700 !ruby/object:Gem::Requirement
215
215
  none: false
216
216
  requirements:
217
217
  - - ! '>='
@@ -219,10 +219,10 @@ dependencies:
219
219
  version: '0'
220
220
  type: :development
221
221
  prerelease: false
222
- version_requirements: *-1071835948
222
+ version_requirements: *70108802312700
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: rake
225
- requirement: &-1071836178 !ruby/object:Gem::Requirement
225
+ requirement: &70108802310780 !ruby/object:Gem::Requirement
226
226
  none: false
227
227
  requirements:
228
228
  - - ! '>='
@@ -230,7 +230,7 @@ dependencies:
230
230
  version: '0'
231
231
  type: :development
232
232
  prerelease: false
233
- version_requirements: *-1071836178
233
+ version_requirements: *70108802310780
234
234
  description: Why another static site generator? Machined is for the developers who
235
235
  know and love the asset pipeline of Rails 3.1 and want to develop blazingly fast
236
236
  static websites. It's built from the ground up using Sprockets 2.0.
@@ -258,6 +258,7 @@ files:
258
258
  - lib/machined/helpers/render_helpers.rb
259
259
  - lib/machined/index.rb
260
260
  - lib/machined/initializable.rb
261
+ - lib/machined/middleware/static.rb
261
262
  - lib/machined/processors/front_matter_processor.rb
262
263
  - lib/machined/processors/layout_processor.rb
263
264
  - lib/machined/server.rb
@@ -284,6 +285,7 @@ files:
284
285
  - spec/machined/helpers/page_helpers_spec.rb
285
286
  - spec/machined/helpers/render_helpers_spec.rb
286
287
  - spec/machined/initializable_spec.rb
288
+ - spec/machined/middleware/static_spec.rb
287
289
  - spec/machined/processors/front_matter_processor_spec.rb
288
290
  - spec/machined/processors/layout_processor_spec.rb
289
291
  - spec/machined/server_spec.rb
@@ -308,7 +310,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
308
310
  version: '0'
309
311
  segments:
310
312
  - 0
311
- hash: 878013729
313
+ hash: -2736667984857958042
312
314
  required_rubygems_version: !ruby/object:Gem::Requirement
313
315
  none: false
314
316
  requirements:
@@ -317,10 +319,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
317
319
  version: '0'
318
320
  segments:
319
321
  - 0
320
- hash: 878013729
322
+ hash: -2736667984857958042
321
323
  requirements: []
322
324
  rubyforge_project: machined
323
- rubygems_version: 1.8.11
325
+ rubygems_version: 1.8.10
324
326
  signing_key:
325
327
  specification_version: 3
326
328
  summary: A static site generator and Rack server built using Sprockets 2.0
@@ -334,6 +336,7 @@ test_files:
334
336
  - spec/machined/helpers/page_helpers_spec.rb
335
337
  - spec/machined/helpers/render_helpers_spec.rb
336
338
  - spec/machined/initializable_spec.rb
339
+ - spec/machined/middleware/static_spec.rb
337
340
  - spec/machined/processors/front_matter_processor_spec.rb
338
341
  - spec/machined/processors/layout_processor_spec.rb
339
342
  - spec/machined/server_spec.rb